JPEGView/Source/C/DitherCopyTo8Odd.c
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

1 line
3.2 KiB
C

/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information. */
/* Contact email: mac@aarongiles.com */
/*********************************************************/
// void DitherCopyTo8Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable,
// DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer,
// short *rgnBuffer, uchar *errorMap, short columns)
// internals:
ulong *src = srcRow; // pointer to the 32-bit source row
uchar *dst = (uchar *)dstRowStart;
ulong pixel; // scratch for the current pixel
long red; // red scratch area
long green; // green scratch area
long blue; // blue scratch area
long red2; // 2 * the red error; used for fast calculations
long green2; // 2 * the green error
long blue2; // 2 * the blue error
long rgnCol; // region column counter
// Skip to the ends of everything here
dst += columns;
src += columns;
eBuffer += columns;
oBuffer += columns;
// initialize our counters and clear out next row
red = green = blue = 0;
eBuffer[-1].red = eBuffer[-1].green = eBuffer[-1].blue = 0;
// set up the region column counter
while (*rgnBuffer++ < columns);
--rgnBuffer;
if (*rgnBuffer == columns) rgnCol = *--rgnBuffer - columns;
else rgnCol = columns - *--rgnBuffer;
// begin main loop here
while (columns--) {
// combine the accumulated errors and round to a pixel value
--oBuffer;
red += oBuffer->red + 8;
red >>= 4;
red = errorMap[red];
green += oBuffer->green + 8;
green >>= 4;
green = errorMap[green];
blue += oBuffer->blue + 8;
blue >>= 4;
blue = errorMap[blue];
// offset the current pixel by the errors
pixel = *--src;
blue += pixel & 0xff;
pixel >>= 8;
green += pixel & 0xff;
pixel >>= 8;
red += pixel & 0xff;
// check for overflows and handle them
if (red > 255) red = 255;
else if (red < 0) red = 0;
if (blue > 255) blue = 255;
else if (blue < 0) blue = 0;
if (green > 255) green = 255;
else if (green < 0) green = 0;
// get the inverse color table entry
pixel = red >> 3;
pixel <<= 5;
pixel += green >> 3;
pixel <<= 5;
pixel += blue >> 3;
pixel = iTable[pixel];
// determine whether or not to draw this pixel, and handle switches
if (rgnCol > 0) {
--dst;
if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer--;
} else {
*--dst = pixel;
if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer--;
}
// calculate the new errors
red -= cTable[pixel].rgb.red >> 8;
green -= cTable[pixel].rgb.green >> 8;
blue -= cTable[pixel].rgb.blue >> 8;
// calculate 2 * the new error for fast ops ahead
red2 = red << 1;
green2 = green << 1;
blue2 = blue << 1;
// store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor
--eBuffer;
eBuffer[-1].red = red;
eBuffer[-1].green = green;
eBuffer[-1].blue = blue;
eBuffer[1].red += (red += red2);
eBuffer[1].green += (green += green2);
eBuffer[1].blue += (blue += blue2);
eBuffer->red += (red += red2);
eBuffer->green += (green += green2);
eBuffer->blue += (blue += blue2);
red += red2;
green += green2;
blue += blue2;
}