home *** CD-ROM | disk | FTP | other *** search
- /* ppm2ilbm module */
- /* written by Günther Röhrich */
- /* this is version 1.5 */
-
- /* this code is tested with Aztec C 5.2a and GNU C 2.5.8 */
- /* NOTE: you will need the newiff V37 or higher package */
- /* (V37 is available on Fish-disk 705) */
-
-
- #include <clib/exec_protos.h>
- #include <libraries/iffparse.h>
- #include <dos/dos.h>
- #include <iffp/ilbmapp.h>
- #include <iffp/packer.h>
- #include <stdio.h>
- #include <graphics/modeid.h>
-
- #include "ppm2AGA.h"
-
- #ifndef __GNUC__
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/iffparse_pragmas.h>
- #endif
-
-
-
- /* needed when compiling with newiff V37 package */
- /* (not needed with V39 or higher) */
-
- #ifndef BMHDF_CMAPOK
- #define BMHDF_CMAPOK (1 << 7)
- #endif
-
- #define random rand
-
- /* externals used by this module */
-
-
- extern int AbortCheck(void);
- extern void PLProgress(ULONG Value, ULONG MaxValue);
- extern volatile unsigned short MaxError, MaxErrorPos;
- extern void EncodeHAM(UBYTE *yorig, UBYTE *yham, char *ColorTable,
- short NumColors, short xsize);
- extern int MapColorASM(colorhist_vector colormap, pixval r1, pixval g1, pixval b1,
- int NumColors);
- extern int ExactColor;
- extern int GfxEnable;
- extern int VGAenable;
- extern int jpegAGA;
- extern char *ILBMfile;
- extern char *BaseName;
- extern ULONG SMR;
- extern ULONG SMR_DisplayID;
-
- /* definitions for the display routines */
-
- extern int InitDisplay(int cols, int rows, ULONG Mode, int NumPlanes);
- extern void SetDisplayColor(int ColorNumber, UBYTE r, UBYTE g, UBYTE b);
- extern void DisplayRow(char *array, int cols, int row);
- extern void CloseDisplay(void);
-
- /* globals defined in this module */
-
- #ifdef DEBUG_ASM
- int MapColor(colorhist_vector colormap, pixval r1, pixval g1, pixval b1,
- int NumColors);
- #endif
-
- unsigned short Mult_Table[2*256];
- unsigned long Mult_Table32[2*256];
- jmp_buf ErrorEnv;
- int cols, rows, rowcnt;
- pixel **pixels;
- pixel *pixrow;
- pixval maxval;
- int ppmformat;
- char ColorTable[64*3] = {0};
- int ColorRegMax;
- unsigned short ConvertMode;
- char *ColorCache; /* a 256K cache for EncodeHAM() */
-
- /* these are needed by Floyd-Steinberg-routines */
- long *thisrerr;
- long *nextrerr;
- long *thisgerr;
- long *nextgerr;
- long *thisberr;
- long *nextberr;
- extern int floyd;
- int fs_direction = 1;
- int Convert4096;
- int Convert262144;
- #define FS_SCALE 1024
-
- /* locals defined in this module */
-
- static FILE *fppm;
- static FILE *ColorMapFile;
- static struct IFFHandle *iff;
- static struct ILBMInfo ilbm;
- static int error;
- static LONG IFFError;
- static unsigned char *coded_rowbuf;
- static unsigned char *hamarray;
- static int returnvalue;
- static void ppmCleanUp(void);
- static int readall;
- static colorhist_vector chv, colormap;
- static BYTE *CompressBuffer;
- static void encode_row(UBYTE *row, int cols, int nPlanes);
- static int ColorShift, NumColors;
- static gray *pgmrow;
-
- static int lumcompare(colorhist_vector ch1, colorhist_vector ch2)
- {
- return (int)((double)PPM_LUMIN(ch1->color) - (double)PPM_LUMIN(ch2->color));
- }
-
-
- int ppm2ilbm(char *PPMfile, ULONG Mode, int NumPlanes, ULONG MaxMem)
- {
- int i, colors;
- pixel *pP;
- unsigned short AbsMaxError = 0;
- unsigned short MaxErrorXPos = 0;
- unsigned short MaxErrorYPos = 0;
-
- /* initialize everything */
- /* this is needed because we may call this function */
- /* multiple times */
- returnvalue = 0;
- fppm = NULL;
- ColorMapFile = NULL;
- readall = 0;
- pixrow = NULL;
- pixels = NULL;
- hamarray = NULL; coded_rowbuf = NULL; ColorCache=NULL;
- memset(&ilbm, 0, sizeof(struct ILBMInfo));
- chv = NULL;
- colormap = NULL;
- CompressBuffer = NULL;
- pgmrow = NULL;
-
-
- /* multiplication table is needed by assembler subroutines */
- for(i=-255; i<256; i++)
- {
- Mult_Table[i+255] = i*i;
- Mult_Table32[i+255] = i*i;
- }
-
-
- /* if we encounter an error we longjmp() to this location */
- /* the ppmCleanUp() function will free all resources allocated */
- /* in this module */
-
- error = setjmp(ErrorEnv);
- if(error != 0)
- {
- ppmCleanUp();
- return error;
- }
-
-
- /* try to open the ppm file */
- fppm = fopen(PPMfile, "r");
- if(!fppm) pm_error("Could not open file %s\n", PPMfile);
-
- /* read the header of the ppm file */
- ppm_readppminit(fppm, &cols, &rows, &maxval, &ppmformat);
-
- #ifdef DEBUG
- pm_message("Cols: %d, Rows: %d, MaxVal: %d, Format: %d\n",
- cols, rows, maxval, ppmformat);
- #else
- pm_message("Cols: %d, Rows: %d, MaxVal: %d\n", cols, rows, maxval);
- #endif
-
- /* Initialize Floyd-Steinberg error vectors. */
- thisrerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- nextrerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- thisgerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- nextgerr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- thisberr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- nextberr = (long*) pm_allocrow( cols + 2, sizeof(long) );
- /* srandom( (int) ( time( 0 ) ^ getpid(0) ) ); */
- for ( i = 0; i < cols + 2; ++i )
- {
- thisrerr[i] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- thisgerr[i] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- thisberr[i] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- /* (random errors in [-1 .. 1]) */
- }
-
- /* try to open the output file */
-
- if(!jpegAGA)
- {
- if(!(ilbm.ParseInfo.iff = AllocIFF()))
- pm_error("Could not do AllocIFF()");
-
- iff = ilbm.ParseInfo.iff;
-
- IFFError = openifile((struct ParseInfo *)&ilbm, (UBYTE *)ILBMfile, IFFF_WRITE);
- if(IFFError) pm_error(""); /* openifile() will print error messages... */
- }
-
- if(Mode == HAM8 || Mode == HAM6 || Mode == COLORMAP)
- {
- int Clustering;
- if(Mode == HAM8)
- {
- NumColors = NumPlanes;
- ColorRegMax = 63;
- ColorShift = 2; /* we only have 256K colors */
- NumPlanes = 8;
- ConvertMode = 1; /* Needed by EncodeHAM() */
- Clustering = 0;
- Convert4096 = 0; /* No 4096-FS conversion */
- if(floyd) Convert262144 = 1; /* 262144 conversion */
-
- }
- else if(Mode == HAM6)
- {
- NumColors = NumPlanes;
- ColorRegMax = 15;
- ColorShift = 4; /* converting to 4096 colors will be done by FS dithering */
- NumPlanes = 6;
- ConvertMode = 0; /* Needed by EncodeHAM() */
- Clustering = 0;
- if(floyd)
- Convert4096 = 1; /* Do 4096-FS conversion */
- Convert262144 = 0;
- }
- else /* COLORMAP */
- {
- NumColors = 1 << NumPlanes;
- ColorRegMax = 255;
- ColorShift = 0; /* we will handle full 16M colors */
- if(ppmformat == PGM_FORMAT || ppmformat == RPGM_FORMAT || ExactColor == 1)
- {
- Clustering = 0;
- }
- else
- {
- Clustering = 2;
- }
- Convert4096 = 0; /* No 4096-FS conversion */
- Convert262144 = 0;
- }
-
- if( cols*rows*3 <= (int)MaxMem)
- {
- /* read the complete picture into memory */
- int row;
- readall = 1;
- pm_message("Reading complete picture into memory...\n");
- pixels = ppm_allocarray(cols, rows);
- for(row = 0; row < rows; ++row)
- {
- if(AbortCheck()) pm_error("^C\n");
- ppm_readppmrow(fppm, pixels[row], cols, maxval, ppmformat);
- if(maxval != ColorRegMax)
- {
- if(maxval == 255)
- {
- for(i=0, pP=pixels[row]; i < cols; ++i, ++pP)
- {
- pP->r = pP->r >> ColorShift;
- pP->g = pP->g >> ColorShift;
- pP->b = pP->b >> ColorShift;
- }
- }
- else
- {
- for(i=0, pP=pixels[row]; i < cols; ++i, ++pP)
- PPM_DEPTH(*pP, *pP, maxval, ColorRegMax);
- }
- }
- }
- }
- else
- {
- rowcnt = 0;
- if(!(pixrow = ppm_allocrow(cols)))
- pm_error("Out of memory.\n");
- }
-
-
- /* allocate enough room for one row of chunky HAM pixels */
- /* (this array will also be used for colormap conversion) */
- if(!(hamarray = malloc(RowBits(cols))))
- pm_error("Out of memory.\n");
-
- /* we only have to clear the space between cols and RowBits(cols) */
- /* hamarray will be larger in most cases because of special alignment*/
- for(i = cols; i < RowBits(cols); i++) hamarray[i] = 0;
- pm_message("Computing colormap...\n");
-
-
- /* now we make a histogram of the picture... */
- /* if we increase Clustering we will find less colors */
- /* we allow a maximum of 10000 colors */
- /* ColorShift is the shift needed for HAM encoding */
- for(i=Clustering; i<5; i++)
- {
- if((chv = ppm_fcomputecolorhist(fppm, cols, rows, 10000, &colors, ColorShift, i)))
- break;
- if(AbortCheck()) pm_error("^C\n");
- pm_message("Could not compute colormap, trying again...\n");
- rowcnt=0;
- if(!readall)
- {
- rewind(fppm); /* re-initialise the ppm pointers for reading again */
- ppm_readppminit(fppm, &cols, &rows, &maxval, &ppmformat);
- }
- }
-
- pm_message("Found %d colors.\n", colors);
-
-
- /* now we try to find a suitable colormap... */
- colormap = mediancut(chv, colors, rows*cols, ColorRegMax, NumColors);
- ppm_freecolorhist(chv); /* we don't need the histogram any more */
- chv = NULL;
- /* sort the colors in ascending luminance order... */
- /* (the first color will be the background color) */
- if(NumColors < colors)
- {
- qsort((char *)colormap, NumColors, sizeof(struct colorhist_item), lumcompare);
- }
- else
- {
- qsort((char *)colormap, colors, sizeof(struct colorhist_item), lumcompare);
- }
-
-
- if(!jpegAGA)
- {
- /* the CompressBuffer is needed by the cmpByteRun1 compressor */
- if(!(CompressBuffer = malloc(MaxPackedSize(RowBytes(cols)))))
- pm_error("Out of memory allocating the compress buffer.\n");
-
- /* the ColorCache is needed by EncodeHAM() for higher speed */
- /* (for HAM6 encoding only 4097 bytes are needed...) */
- if(!(ColorCache = malloc(262145)))
- pm_error("Out of memory allocating the color cache.\n");
-
- /* the coded_rowbuf is needed by the IFF encoder */
- if(!(coded_rowbuf = (unsigned char *)malloc(RowBytes(cols))))
- pm_error("Out of memory allocating coded_rowbuf.\n");
- for(i=RowBytes(cols)-1; i>=0; i--) coded_rowbuf[i]=0;
-
- /* write the FORM chunk */
- IFFError = PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);
- if(IFFError) pm_error("Error writing FORM chunk.\n");
-
- /* initialize the BMHD chunk */
- ilbm.Bmhd.w = cols;
- ilbm.Bmhd.h = rows; /* Width, height in pixels */
- ilbm.Bmhd.x = 0;
- ilbm.Bmhd.y = 0; /* x, y position for this bitmap */
- ilbm.Bmhd.nPlanes = NumPlanes; /* # of planes (not including mask) */
- ilbm.Bmhd.masking = mskNone;
- ilbm.Bmhd.compression = cmpByteRun1;
- ilbm.Bmhd.flags = BMHDF_CMAPOK; /* CMAP has 8 significant bits */
- ilbm.Bmhd.transparentColor = 0;
- ilbm.Bmhd.xAspect = cols;
- ilbm.Bmhd.yAspect = rows; /* xAspect, yAspect */
- ilbm.Bmhd.pageWidth = cols;
- ilbm.Bmhd.pageHeight = rows; /* pageWidth, pageHeight */
-
- /* write the BMHD chunk */
- IFFError = putbmhd(iff, &ilbm.Bmhd);
- if(IFFError) pm_error("Error writing BMHD chunk.\n");
-
- if(GfxEnable) InitDisplay(cols, rows, Mode, NumPlanes);
- }
-
- if(Mode == HAM8 || Mode == HAM6)
- {
- /* fill in the ColorTable in B R G order */
- /* (this is better for HAM encoding) */
- for(i=0; i<NumColors; i++)
- {
- ColorTable[i*3] = PPM_GETB(colormap[i].color);
- ColorTable[i*3+1] = PPM_GETR(colormap[i].color);
- ColorTable[i*3+2] = PPM_GETG(colormap[i].color);
- if(!jpegAGA)
- {
- if(ColorShift == 4)
- SetDisplayColor(i, (PPM_GETR(colormap[i].color) << ColorShift) |
- PPM_GETR(colormap[i].color),
- (PPM_GETG(colormap[i].color) << ColorShift) |
- PPM_GETG(colormap[i].color),
- (PPM_GETB(colormap[i].color) << ColorShift) |
- PPM_GETB(colormap[i].color));
- else
- SetDisplayColor(i, (PPM_GETR(colormap[i].color) << ColorShift),
- (PPM_GETG(colormap[i].color) << ColorShift),
- (PPM_GETB(colormap[i].color) << ColorShift));
- }
- }
- free(colormap); /* we don't need the colormap any more */
- colormap = NULL;
-
- if(jpegAGA)
- {
- char *MapDir;
- unsigned short MagicNumber = 0x1203; /* guess what this means! */
- int Reserved=0;
- unsigned char color;
- MapDir = getenv("MAPDIR");
-
- ColorMapFile = fopen(ILBMfile, "w");
-
- if(!ColorMapFile && !BaseName)
- {
- if(MapDir)
- if(strlen(MapDir) != 0)
- {
- char *MapDirName;
- int pos,i;
- MapDirName = malloc(strlen(MapDir)+strlen(ILBMfile)+5); /* worst case */
- if(!MapDirName) pm_error("Out of memory.\n");
- strcpy(MapDirName, MapDir);
-
- i = strlen(MapDirName);
- if(MapDirName[i-1] != '/' && MapDirName[i-1] != ':')
- {
- strcat(MapDirName, "/");
- i++;
- }
- i = strlen(ILBMfile);
- while(i > 0 && ILBMfile[i-1] != '/' && ILBMfile[i-1] != ':') i--;
- strcat(MapDirName, &ILBMfile[i]);
- ColorMapFile = fopen(MapDirName, "w");
- if(ColorMapFile) pm_message("Writing mapfile: %s\n", MapDirName);
- }
- }
- else if(!ColorMapFile && BaseName && MapDir)
- if(strlen(MapDir) != 0)
- {
- char *NewName;
- int i;
- NewName = malloc(strlen(MapDir)+strlen(BaseName)+strlen(ILBMfile)); /* worst case */
- if(!NewName) pm_error("Out of memory.\n");
- strcpy(NewName, MapDir);
- i=strlen(NewName);
- if(NewName[i-1] != '/' && NewName[i-1] != ':')
- {
- strcat(NewName, "/");
- i++;
- }
- strcat(NewName, BaseName);
- i=strlen(ILBMfile);
- while(i > 0 && ILBMfile[i-1] != '/' && ILBMfile[i-1] != ':') i--;
- if(strlen(ILBMfile) > i+3)
- {
- strcat(NewName, &ILBMfile[i+3]);
- i = strlen(NewName) - 4;
- if(i < 1) pm_error("Wrong mapfile name.\n");
- while(i > 0 && NewName[i-1] != '.') i--;
- if(NewName[i-1] == '.')
- {
- strcpy(&NewName[i], "map");
- printf("%s\n", NewName);
- ColorMapFile = fopen(NewName, "w");
- }
- }
- free(NewName);
- }
-
-
- if(!ColorMapFile) pm_error("Could not open color map file for jpegAGA.\n");
-
- if(fwrite(&MagicNumber, 2, 1, ColorMapFile) != 1) pm_error("Write error.\n");
- if(fwrite(&Reserved, 4, 1, ColorMapFile) != 1) pm_error("Write error.\n");
- if(fwrite(ColorTable, 64*3, 1, ColorMapFile) != 1) pm_error("Write error.\n");
- pm_message("Colormap file for jpegAGA/PhotoCDAGA created.\n");
- ppmCleanUp();
- return 0;
- }
-
- memset(ColorCache, 0, 262145); /* clear the color cache */
-
- do
- {
- int y;
- rowcnt=0;
-
- /* if we don't need an additional color the color cache */
- /* will remain valid and should not be cleared */
-
- memset(ColorCache, 0, 262145); /* clear the color cache */
-
-
- if(!readall)
- {
- rewind(fppm);
- ppm_readppminit(fppm, &cols, &rows, &maxval, &ppmformat);
- }
-
- /* if we have all colors we can write the CMAP chunk */
- if(NumColors == ColorRegMax+1)
- {
- IFFError = PushChunk(iff, 0, ID_CMAP, (ColorRegMax+1)*3);
- if(IFFError) pm_error("Error writing CMAP header.\n");
-
- for( i = 0; i <= ColorRegMax; i++)
- {
- ColorRegister cmapReg;
- if(ColorShift == 4) /* HAM6 */
- {
- cmapReg.red = (ColorTable[i*3+1] << ColorShift)
- | ColorTable[i*3+1]; /* red */
- cmapReg.green = (ColorTable[i*3+2] << ColorShift)
- | ColorTable[i*3+2]; /* green */
- cmapReg.blue = (ColorTable[i*3] << ColorShift)
- | ColorTable[i*3]; /* blue */
- }
- else /* HAM8 */
- {
- cmapReg.red = ColorTable[i*3+1] << ColorShift; /* red */
- cmapReg.green = ColorTable[i*3+2] << ColorShift; /* green */
- cmapReg.blue = ColorTable[i*3] << ColorShift; /* blue */
- }
- IFFError = WriteChunkBytes(iff, (UBYTE *)&cmapReg, 3);
- if(IFFError!=3) pm_error("Error writing CMAP chunk.\n");
- }
- IFFError = PopChunk(iff); /* close CMAP */
- if(IFFError) pm_error("Error closing CMAP.\n");
-
- /* write the CAMG chunk */
- if(SMR)
- {
- ilbm.camg = SMR_DisplayID;
- }
- else
- {
- if(VGAenable)
- {
- if(cols > 370 || rows > 260)
- {
- ilbm.camg = VGAPRODUCTHAM_KEY;
- }
- else
- {
- ilbm.camg = VGALORESHAMDBL_KEY;
- }
- }
- else
- {
- ilbm.camg = HAM;
- if(cols > 370) ilbm.camg = ilbm.camg | HIRES;
- if(rows > 280) ilbm.camg = ilbm.camg | LACE;
- }
- }
- IFFError = putcamg(iff, &ilbm.camg);
- if(IFFError) pm_error("Error writing CAMG chunk.\n");
-
- /* start with the BODY chunk */
- IFFError = PushChunk(iff, 0, ID_BODY, IFFSIZE_UNKNOWN);
- if(IFFError) pm_error("Error writing BODY header.\n");
- }
-
- /* set a dummy value for AbsMaxError */
- /* it will contain the maximum error for the complete picture */
- AbsMaxError=0;
-
- for(y=0; y<rows; y++)
- {
- pixel *nextrow;
-
- MaxError = 0;
-
- nextrow = next_pixrow(fppm, y, ColorShift);
-
- if(AbortCheck()) pm_error("^C\n");
-
- EncodeHAM(nextrow, hamarray, ColorTable, NumColors*3, (short)cols);
-
-
- /* remember the color of the pixel with the maximum error */
- /* even if MaxError == 0 we will get a valid entry in the */
- /* colormap but it will not be used by the picture */
- if(MaxError > AbsMaxError)
- {
- MaxErrorXPos = MaxErrorPos;
- MaxErrorYPos = y;
- AbsMaxError = MaxError;
-
- /* use the color of the pixel with the maximum error as */
- /* a ColorTable entry */
- /* we will have to recompute the picture if we want to */
- /* use the additional color */
- if(NumColors <= ColorRegMax)
- {
- ColorTable[NumColors*3] = PPM_GETB(pixrow[MaxErrorXPos]);
- ColorTable[NumColors*3+1] = PPM_GETR(pixrow[MaxErrorXPos]);
- ColorTable[NumColors*3+2] = PPM_GETG(pixrow[MaxErrorXPos]);
- }
- }
-
- /* if all colors are set we can write our row to the BODY chunk */
- if(NumColors == ColorRegMax+1)
- {
- encode_row(hamarray, cols, NumPlanes);
- }
- DisplayRow(hamarray, cols, y);
- }
-
- /* this is only for debugging purposes */
- if(NumColors <= ColorRegMax)
- {
- #ifdef DEBUG
- pm_message("Max Error: %hd ", AbsMaxError);
- #endif
- if(AbsMaxError == 0)
- {
- printf("\n");
- }
- else
- {
- #ifdef DEBUG
- pm_message("Color %hd, XPos: %hd, YPos: %hd\n", NumColors, MaxErrorXPos, MaxErrorYPos);
- #endif
- }
- }
- SetDisplayColor(NumColors, ColorTable[NumColors*3+1] << ColorShift,
- ColorTable[NumColors*3+2] << ColorShift,
- ColorTable[NumColors*3] << ColorShift);
- NumColors = NumColors + 1;
-
- /* finish if we have set all colors */
- } while(NumColors <= ColorRegMax+1);
-
-
- #ifdef DEBUG
- pm_message("Max Error: %hd, XOffset: %hd YOffset: %hd\n",
- AbsMaxError, MaxErrorXPos, MaxErrorYPos);
-
- pm_message("Colortable: ");
- for(i=0; i<=ColorRegMax; i++)
- {
- pm_message("%hd,%hd,%hd ",ColorTable[i*3],
- ColorTable[i*3+1],ColorTable[i*3+2]);
- }
- pm_message("\n");
- #endif
-
- /* close the BODY chunk */
- IFFError = PopChunk(iff);
- if(IFFError) pm_message("Error closing the BODY chunk.\n");
- }
-
-
- else if(Mode == COLORMAP)
- {
- /* if floyd is nonzero we will use Floyd-Steinberg dithering */
- int row, fs_direction;
- register int col, limitcol, ind;
- register pixel *pP;
- register long sg, sr, sb, err;
- long *temperr;
-
- /*
- ** map the colors in the image to their closest match in the
- ** new colormap, and write 'em out.
- */
-
- pm_message( "Mapping image to new colors...\n" );
-
- /* write the CMAP chunk */
- IFFError = PushChunk(iff, 0, ID_CMAP, NumColors*3);
- if(IFFError) pm_error("Error writing CMAP header.\n");
- for( i = 0; i < NumColors; i++)
- {
- ColorRegister cmapReg;
- cmapReg.red = PPM_GETR( colormap[i].color ); /* red */
- cmapReg.green = PPM_GETG( colormap[i].color ); /* green */
- cmapReg.blue = PPM_GETB( colormap[i].color ); /* blue */
- SetDisplayColor(i, cmapReg.red, cmapReg.green, cmapReg.blue);
- IFFError = WriteChunkBytes(iff, (UBYTE *)&cmapReg, 3);
- if(IFFError!=3) pm_error("Error writing CMAP chunk.\n");
- }
- IFFError = PopChunk(iff); /* close CMAP */
- if(IFFError) pm_error("Error closing CMAP.\n");
-
- /* write the CAMG chunk */
- if(SMR)
- {
- ilbm.camg = SMR_DisplayID;
- }
- else
- {
- ilbm.camg = 0;
- if(VGAenable)
- {
- if(cols > 370 || rows > 260)
- ilbm.camg = VGAPRODUCT_KEY;
- else
- ilbm.camg = VGALORESDBL_KEY;
- }
- else
- {
- if(cols > 370) ilbm.camg = ilbm.camg | HIRES;
- if(rows > 280) ilbm.camg = ilbm.camg | LACE;
- }
- }
- IFFError = putcamg(iff, &ilbm.camg);
- if(IFFError) pm_error("Error writing CAMG chunk.\n");
-
- /* start with the BODY chunk */
- IFFError = PushChunk(iff, 0, ID_BODY, IFFSIZE_UNKNOWN);
- if(IFFError) pm_error("Error writing BODY header.\n");
-
- rowcnt=0;
- if(!readall)
- {
- rewind(fppm);
- ppm_readppminit(fppm, &cols, &rows, &maxval, &ppmformat);
- }
-
- if ( floyd )
- {
- fs_direction = 1;
- }
- for ( row = 0; row < rows; ++row )
- {
- /* PLProgress(row, rows); */
- if(AbortCheck()) pm_error("^C\n");
- if ( floyd )
- for ( col = 0; col < cols + 2; ++col )
- nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
- if ( ( ! floyd ) || fs_direction )
- {
- col = 0;
- limitcol = cols;
- /* pP = pixels[row]; */
- pP = next_pixrow(fppm, row, ColorShift);
- }
- else
- {
- col = cols - 1;
- limitcol = -1;
- /* pP = &(pixels[row][col]); */
- pP = &(next_pixrow(fppm, row, ColorShift)[col]);
- }
- do
- {
- if ( floyd )
- {
- /* Use Floyd-Steinberg errors to adjust actual color. */
- sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
- sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
- sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
- if ( sr < 0 ) sr = 0;
- else if ( sr > maxval ) sr = maxval;
- if ( sg < 0 ) sg = 0;
- else if ( sg > maxval ) sg = maxval;
- if ( sb < 0 ) sb = 0;
- else if ( sb > maxval ) sb = maxval;
- PPM_ASSIGN( *pP, sr, sg, sb );
- }
-
- /* use the assembler subroutine for the colormap search */
- /* this will consume most of the CPU time */
- ind = MapColorASM(colormap, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP),
- NumColors);
-
- /* compare the results of the ASM versus the C routine */
- /* if they differ the ASM routine has a bug... */
- /* (we don't need them because they are the same now) */
- #ifdef DEBUG_ASM
- if(ind != MapColor(colormap, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP),
- NumColors))
- pm_message("Diff: row %d col %d r %d g %d b %d\n", row,col,
- (int)PPM_GETR(*pP), (int)PPM_GETG(*pP), (int)PPM_GETB(*pP));
- #endif
-
- if ( floyd )
- {
- /* Propagate Floyd-Steinberg error terms. */
- if ( fs_direction )
- {
- err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
- thisrerr[col + 2] += ( err * 7 ) / 16;
- nextrerr[col ] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col + 2] += ( err ) / 16;
- err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
- thisgerr[col + 2] += ( err * 7 ) / 16;
- nextgerr[col ] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col + 2] += ( err ) / 16;
- err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
- thisberr[col + 2] += ( err * 7 ) / 16;
- nextberr[col ] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col + 2] += ( err ) / 16;
- }
- else
- {
- err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
- thisrerr[col ] += ( err * 7 ) / 16;
- nextrerr[col + 2] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col ] += ( err ) / 16;
- err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
- thisgerr[col ] += ( err * 7 ) / 16;
- nextgerr[col + 2] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col ] += ( err ) / 16;
- err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
- thisberr[col ] += ( err * 7 ) / 16;
- nextberr[col + 2] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col ] += ( err ) / 16;
- }
- }
-
- /* *pP = colormap[ind].color; */
- hamarray[col] = (unsigned char)ind;
-
- if ( ( ! floyd ) || fs_direction )
- {
- ++col;
- ++pP;
- }
- else
- {
- --col;
- --pP;
- }
- }
- while ( col != limitcol );
-
- if ( floyd )
- {
- temperr = thisrerr;
- thisrerr = nextrerr;
- nextrerr = temperr;
- temperr = thisgerr;
- thisgerr = nextgerr;
- nextgerr = temperr;
- temperr = thisberr;
- thisberr = nextberr;
- nextberr = temperr;
- fs_direction = ! fs_direction;
- }
-
- /* ppm_writeppmrow( stdout, pixels[row], cols, maxval, 0 ); */
- /* write one row to the BODY chunk */
- encode_row(hamarray, cols, NumPlanes);
- DisplayRow(hamarray, cols, row);
- }
- IFFError = PopChunk(iff); /* close the BODY */
- if(IFFError) pm_error("Error closing the BODY chunk.\n");
- }
- }
-
- closeifile((struct ParseInfo *)&ilbm);
- ppmCleanUp();
- return 0;
- }
-
-
- /* free all resources used by this module */
- void ppmCleanUp(void)
- {
- CloseDisplay();
- if(colormap) free(colormap);
- if(pgmrow) pgm_freerow(pgmrow);
- if(coded_rowbuf) free(coded_rowbuf);
- if(CompressBuffer) free(CompressBuffer);
- if(ColorCache) free(ColorCache);
- if(chv) free(chv);
- if(hamarray) free(hamarray);
- if(pixels)
- {
- ppm_freearray(pixels, rows);
- }
- else
- {
- if(pixrow) pbm_freerow(pixrow);
- }
- if(fppm) fclose(fppm);
-
- if(jpegAGA)
- {
- if(ColorMapFile)
- {
- fclose(ColorMapFile);
- ColorMapFile = NULL;
- }
- }
- else
- {
- if(ilbm.ParseInfo.opened)
- {
- closeifile((struct ParseInfo *)&ilbm);
- remove(ILBMfile);
- }
- if(ilbm.ParseInfo.iff) FreeIFF(ilbm.ParseInfo.iff);
- }
- }
-
-
-
- /* convert one row from chunky to planar, compress it, */
- /* and write it to the BODY chunk */
-
- /* encode algorithm by Johan Widen (jw@jwdata.se) */
- /* modified by Günther Röhrich */
-
- const unsigned char bit_mask[] = {1, 2, 4, 8, 16, 32, 64, 128};
-
- static void
- encode_row(UBYTE *row, int cols, int nPlanes)
- {
- register int plane, col;
- int bytes;
- LONG packedRowBytes;
- BYTE *source;
- BYTE *destination;
-
- bytes = RowBytes(cols);
-
- /* Encode and write raw bytes in plane-interleaved form. */
- for( plane = 0; plane < nPlanes; plane++ )
- {
- int mask, cbit, wr;
- unsigned char *cp;
- UBYTE *rp;
-
- mask = 1 << plane;
- cbit = -1;
- cp = coded_rowbuf-1;
- rp = row;
- for( col = 0; col < cols; col++, cbit--, rp++ )
- {
- if( cbit < 0 )
- {
- cbit = 7;
- *++cp = 0;
- }
- if( *rp & mask )
- *cp |= bit_mask[cbit];
- }
- /* wr = fwrite(coded_rowbuf, 1, bytes, stdout); */
-
- /* compress the row */
- source = coded_rowbuf;
- destination = CompressBuffer;
- packedRowBytes = packrow(&source, &destination, bytes);
-
- /* write the compressed row to the BODY chunk */
- IFFError = WriteChunkBytes(iff, CompressBuffer, packedRowBytes);
- if(IFFError!=packedRowBytes) pm_error("Error writing BODY chunk.\n");
- }
- }
-
-
- #ifdef DEBUG_ASM
- /* this is the C version of the colormap search routine */
- /* (it is now replaced by the ASM version) */
-
- /* search colormap for closest match. */
- int MapColor(colorhist_vector colormap, pixval r, pixval g, pixval b,
- int newcolors)
- {
- int ind;
- register int i, r1, g1, b1, r2, g2, b2;
- register long dist, newdist;
- r1 = r;
- g1 = g;
- b1 = b;
- dist = 2000000000;
- for ( i = 0; i < newcolors; ++i )
- {
- r2 = PPM_GETR( colormap[i].color );
- g2 = PPM_GETG( colormap[i].color );
- b2 = PPM_GETB( colormap[i].color );
- newdist = ( r1 - r2 ) * ( r1 - r2 ) +
- ( g1 - g2 ) * ( g1 - g2 ) +
- ( b1 - b2 ) * ( b1 - b2 );
- if ( newdist < dist )
- {
- ind = i;
- dist = newdist;
- }
- }
- return ind;
- }
- #endif
-
-
-