Code:
int Filter( IMAGE *Image, BIT *pos, ulong p )
{
BUFFERS *Buffers = Image->Buffers;
BUFFER *Data = AccessBuffer( Buffers, Image->DataID );
BUFFER *View = AccessBuffer( Buffers, Image->ViewID );
uchar *view = View->addr, *data = Data->addr;
ulong size = (Image->Flags & 2) + 1, A, B, C = 0;
ulong x = p, col, Cols = Image->Cols, RowSize = Cols * sizeof(ulong);
uchar *a = (uchar*)&A, *b, *c, filter = 0, bit;
FILE *errors = Buffers->Alloc->errors;
FILE *detailed = Image->Buffers->Alloc->detailed;
ForeBits( &filter, data, pos->abs, 3 );
ECHO
(
detailed,
fprintf
(
detailed,
"Filter( %p, %7" PRIuMAX ", %7lu ) filter = %u\n",
(void*)Image, pos->abs, p, filter
)
);
AddBit( pos, data, 3 );
if ( filter > 1 && x < RowSize )
{
ECHO( errors, ECHO_ERR( errors, EINVAL ) );
return EINVAL;
}
switch ( filter )
{
/* raw */
case 0:
for ( col = 0; col < Cols; ++col )
{
uchar raw[sizeof(ulong)] = {0};
ForeBits( raw, data, pos->abs, Image->Depth );
AddBit( pos, data, Image->Depth );
for ( B = 0; B < size; ++B, ++x )
view[x] = raw[B];
x += sizeof(ulong) - size;
}
break;
/* pixel behind */
case 1:
A = 0;
for ( col = 0; col < Cols; ++col )
{
uchar raw[sizeof(ulong)] = {0};
ForeBits( raw, data, pos->abs, Image->Depth );
AddBit( pos, data, Image->Depth );
for ( B = 0; B < size; ++B, ++x )
a[B] = view[x] = raw[B] + a[B];
x += sizeof(ulong) - size;
}
break;
/* pixel above */
case 2:
for ( col = 0; col < Cols; ++col )
{
uchar raw[sizeof(ulong)] = {0};
ForeBits( raw, data, pos->abs, Image->Depth );
AddBit( pos, data, Image->Depth );
b = view + (x - RowSize);
for ( B = 0; B < size; ++B, ++x )
view[x] = raw[B] + b[B];
x += sizeof(ulong) - size;
}
break;
/* pixel average */
case 3:
A = 0;
for ( col = 0; col < Cols; ++col )
{
uchar raw[sizeof(ulong)] = {0};
ForeBits( raw, data, pos->abs, Image->Depth );
AddBit( pos, data, Image->Depth );
b = view + (x - RowSize);
for ( B = 0; B < size; ++B, ++x )
a[B] = view[x] = raw[B] + (((uint)a[B] + (uint)b[B]) / 2);
x += sizeof(ulong) - size;
}
break;
/* paeth predictor */
case 4:
A = 0;
c = (uchar*)&C;
for ( col = 0; col < Cols; ++col )
{
uchar raw[sizeof(ulong)] = {0};
uchar *t = b = view + (x - RowSize);
ForeBits( raw, data, pos->abs, Image->Depth );
AddBit( pos, data, Image->Depth );
for ( B = 0; B < size; ++B, ++x )
a[B] = view[x] =
raw[B] + PaethPredictor( a[B], b[B], c[B] );
x += sizeof(ulong) - size;
c = t;
}
break;
default:
ECHO( errors, ECHO_ERR( errors, EINVAL ) );
return EINVAL;
}
return 0;
}
int ScanLines( IMAGE *Image )
{
ulong Cols = Image->Cols;
ulong RowSize = Cols * sizeof(ulong);
ulong p;
BUFFER *Data = AccessBuffer( Image->Buffers, Image->DataID );
BIT pos;
SetBit( &pos, Data->addr, 0 );
for ( p = 0; p < Image->Pixels; p += RowSize )
{
int err = Filter( Image, &pos, p );
if ( err )
{
FILE *errors = Image->Buffers->Alloc->errors;
ECHO( errors, ECHO_ERR( errors, err ) );
return err;
}
}
return 0;
}