/* Copyright 1990 by Christopher A. Wichura. See file GIFMachine.doc for full description of rights. */ #include "GIFMachine.h" extern struct GIFdescriptor gdesc; EXTERNBITPLANE; extern char *AbortMsg; extern BOOL Laced; UWORD *SHAMmem; struct RGB Palette[16]; extern UBYTE PaletteBuf[MAXCOLOURS]; extern ULONG ColourBuf[MAXCOLOURS]; static ULONG ErrBuf[MAXCOLOURS]; #define ISLACED (Laced && (y != gdesc.gd_Height - 1)) void GIFtoSHAM(void) { register UWORD x; register UWORD current; register int index; register int index2; ULONG error; UWORD y; int Pal; int ShamIndex; int colours; ULONG TotalErr, LineErr; ULONG bestpal; ULONG besterr; UBYTE CurrentRed, CurrentGreen, CurrentBlue; UBYTE PreviousRed, PreviousGreen, PreviousBlue; MyPrintf("...Converting to SHAM format.\n......Line"); ShamIndex = TotalErr = 0; /* palette zero is always the background colour. regardless of what the GIF specified for the background, we always use black. this is a kludge to get around a hardware `feature' that causes all overscanned screens to have a black background regardless of what the background was specified to be. */ Palette[0].rgb_Red = Palette[0].rgb_Green = Palette[0].rgb_Blue = 0; for (y = 0; y < gdesc.gd_Height; y += (ISLACED ? 2 : 1)) { if (ISLACED) MyPrintf("s %5ld-%5ld", y, y + 1); else MyPrintf(" %5ld", y); if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { MyPrintf("\n%s", AbortMsg); MyExit(ABORTEXITVAL); } memset((char *)ColourBuf, 0, sizeof(ColourBuf)); for (colours = index2 = 0; index2 < (ISLACED ? 2 : 1); index2++) for (x = 0; x < gdesc.gd_Width; x++) { current = GetValue(x, y + index2); if (ColourBuf[current]++ == 0) colours++; } MyPrintf(", %4ld unique colours", colours); memset((char *)PaletteBuf, 0, sizeof(PaletteBuf)); for (index = 0; index < MAXCOLOURS; index++) { if (ColourBuf[index] == 0) continue; ErrBuf[index] = RGBdiff(GetRed(index), GetGreen(index), GetBlue(index), Palette[0].rgb_Red, Palette[0].rgb_Green, Palette[0].rgb_Blue); } for (Pal = 1; Pal < 16; Pal++) { for (besterr = index = 0; index < MAXCOLOURS; index++) { if (ColourBuf[index] == 0) continue; if (ErrBuf[index] * ColourBuf[index] >= besterr) { bestpal = index; besterr = ErrBuf[index] * ColourBuf[index]; } } Palette[Pal].rgb_Red = GetRed(bestpal); Palette[Pal].rgb_Green = GetGreen(bestpal); Palette[Pal].rgb_Blue = GetBlue(bestpal); for (index = 0; index < MAXCOLOURS; index++) { if (ColourBuf[index] == 0) continue; error = RGBdiff(GetRed(index), GetGreen(index), GetBlue(index), Palette[Pal].rgb_Red, Palette[Pal].rgb_Green, Palette[Pal].rgb_Blue); if (error < ErrBuf[index]) { ErrBuf[index] = error; PaletteBuf[index] = Pal; } } } for (index = 0; index < 16; index++) SHAMmem[ShamIndex++] = (UWORD)( Palette[index].rgb_Red << 8 | Palette[index].rgb_Green << 4 | Palette[index].rgb_Blue); for (index2 = 0; index2 < (ISLACED ? 2 : 1); index2++) { PreviousRed = Palette[0].rgb_Red; PreviousGreen = Palette[0].rgb_Green; PreviousBlue = Palette[0].rgb_Blue; for (LineErr = x = 0; x < gdesc.gd_Width; x++) { current = GetValue(x, y + index2); CurrentRed = GetRed(current); CurrentGreen = GetGreen(current); CurrentBlue = GetBlue(current); besterr = ErrBuf[current]; bestpal = PaletteBuf[current]; error = RGBdiff( CurrentRed, CurrentGreen, CurrentBlue, CurrentRed, PreviousGreen, PreviousBlue); if (error < besterr) { besterr = error; bestpal = 16; } error = RGBdiff( CurrentRed, CurrentGreen, CurrentBlue, PreviousRed, CurrentGreen, PreviousBlue); if (error < besterr) { besterr = error; bestpal = 17; } error = RGBdiff( CurrentRed, CurrentGreen, CurrentBlue, PreviousRed, PreviousGreen, CurrentBlue); if (error < besterr) { besterr = error; bestpal = 18; } if (bestpal < 16) { PutValue(x, y + index2, bestpal); PreviousRed = Palette[bestpal].rgb_Red; PreviousGreen = Palette[bestpal].rgb_Green; PreviousBlue = Palette[bestpal].rgb_Blue; } else if (bestpal == 16) { PutValue(x, y + index2, CurrentRed | 0x20); PreviousRed = CurrentRed; } else if (bestpal == 17) { PutValue(x, y + index2, CurrentGreen | 0x30); PreviousGreen = CurrentGreen; } else { PutValue(x, y + index2, CurrentBlue | 0x10); PreviousBlue = CurrentBlue; } LineErr += besterr; } TotalErr += LineErr; } MyPrintf("\x9B" "%sD\x9BK", (ISLACED ? "34" : "27")); } { ULONG ErrPerPixel; char TextBuf[10]; ErrPerPixel = ((TotalErr / gdesc.gd_Height) * 1000) / gdesc.gd_Width; MySPrintf(TextBuf, "%ld.%03ld", ErrPerPixel / 1000, ErrPerPixel % 1000); MyPrintf("\x9B" "4DTotal colour error = %ld, Mean per line = %ld, Per pixel = %s.\n", TotalErr, TotalErr / gdesc.gd_Height, TextBuf); } }