gi - a DPaint to C converter
farren at well.UUCP
farren at well.UUCP
Sun Feb 2 19:14:18 AEST 1986
This is the source for gi, the Amiga image data generation program.
For a complete description, read the posting in net.micro.amiga.
#------------------ CUT HERE --------------------------#
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the file:
# gi.c
# Created: Sat Feb 1 23:54:44 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'gi.c'"
sed 's/^X//' << \SHAR_EOF > 'gi.c'
X/**********************************************************
X* *
X* gi - a DeluxePaint to C data converter *
X* *
X* Copyright (c) 1986, Michael J. Farren *
X* This program may be freely distributed by any means *
X* desired, but may not be sold in any form. *
X* *
X**********************************************************/
X
X#include <stdio.h>
X#undef NULL
X#include <exec/types.h>
X
Xstruct BitMapHeader {
X UWORD w,h; /* raster width, height, in pixels */
X WORD x,y; /* pixel position for saved image */
X UBYTE nplanes; /* number of bit planes in source */
X UBYTE masking; /* masking technique */
X UBYTE compression; /* compression algorithm */
X UBYTE pad1; /* padding to justify next entry */
X UWORD transColor; /* transparent "color number" */
X UBYTE xAsp, yAsp; /* x:y aspect ratio */
X WORD pageW, pageH; /* source "page" size in pixels */
X } bmhd;
XUBYTE Cmap[96],old_cmap[96]; /* 32 color storage */
XAPTR *(raster_lines[400][6]); /* pointers to raster lines in bit planes */
XLONG colors_in_byte[8], colors_used[32], tran_table[32];
XLONG twopowers[7] = { 1, 2, 4, 8, 16, 32, 64 };
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X WORD bytes_per_line; /* Number of bytes per raster line */
X FILE *i_file, *o_file;
X UBYTE *buff_pointer, *body_data; /* storage pointers */
X UBYTE *data_pointer, *buff_pointer_save;
X LONG body_data_size, buff_size; /* size storage */
X LONG i, j, k, temp; /* various temporary variables */
X UBYTE tempbyte;
X
X /* Check arguments, and try to open i/o files */
X
X if(argc != 3) {
X printf("\nUsage -> getimage <input file> <output file>\n");
X exit(20);
X }
X
X if((i_file = fopen(argv[1], "r")) == 0 ) {
X printf("\nCould not open input file %s!\n", argv[1]);
X exit(20);
X }
X
X if((o_file = fopen(argv[2], "w")) == 0 ) {
X printf("\nCould not open output file %s!\n", argv[2]);
X exit(20);
X }
X
X /* Files are O.K. - skip over first 20 bytes ("FORM", length, "ILBM",
X "BMHD", length) */
X
X printf("\nReading input file...\n");
X if(fseek(i_file, 20L, 0)) read_error();
X
X /* Now, read in the BMHD structure */
X
X chkread(&bmhd, sizeof(struct BitMapHeader), i_file);
X
X /* Skip the CMAP label, and read in the color map length, then the color
X map data. We assume that the color map length accurately reflects
X the number of bit planes, so don't bother to check the header entry
X bmhd.nplanes. Also, all Amiga color maps will have an even number of
X entries, so don't bother padding the read out. */
X
X if(fseek(i_file, 4L, 1)) read_error(); /* skip the label */
X chkread(&temp, sizeof(LONG), i_file); /* read the length */
X
X i = 0; /* and read in the map */
X while( i < temp)
X chkread(&Cmap[i++], 1, i_file);
X
X /* Now, check the next header. If it isn't "GRAB", this isn't a
X brush file, so get out */
X
X chkread(&temp, sizeof(LONG), i_file);
X if(temp != ('G'<<24 | 'R'<<16 | 'A'<<8 | 'B')) {
X printf("\nThe input file is not a DeluxePaint brush file!\n");
X exit(20);
X }
X
X /* It's probably a brush file. Skip the next 12 bytes (the GRAB length,
X the GRAB coords, and the "BODY" label), then get the body length,
X then read the body data into body_data[] */
X
X if(fseek(i_file, 12L, 1)) read_error();
X chkread(&body_data_size, sizeof(LONG), i_file);
X body_data = AllocMem(body_data_size, NULL);
X chkread(body_data, body_data_size, i_file);
X
X /* Now, start the good stuff. First, allocate enough memory to hold
X the entire bitmap for the image. */
X
X bytes_per_line = (bmhd.w & 7 ? bmhd.w+8 : bmhd.w) >> 3;
X if(bytes_per_line & 1) bytes_per_line++;
X
X buff_size = bytes_per_line * bmhd.h * bmhd.nplanes;
X buff_pointer = AllocMem(buff_size, NULL );
X buff_pointer_save = buff_pointer;
X data_pointer = body_data;
X
X /* Next, go through the file line by line, bit plane by bit plane,
X and extract the image data, putting it into bitmap. As this is
X being done, save pointers to each line in the raster_lines array. */
X
X for(i=0; i!=bmhd.h; i++) { /* # of lines high */
X for(j=0; j!=bmhd.nplanes; j++) { /* # of planes */
X raster_lines[i][j] = buff_pointer; /* set the pointer */
X if(bmhd.compression == 1) {
X
X /* if compressed, decompress */
X
X expand_map(bytes_per_line, buff_pointer, &data_pointer);
X }
X else {
X for(k=0; k!=bytes_per_line; k++) {
X *(buff_pointer+k) = *(data_pointer++);
X }
X }
X buff_pointer += bytes_per_line;
X }
X }
X
X FreeMem(body_data, body_data_size); /* deallocate the body data block */
X
X/* Now, go through the data, determining the different colors used */
X
Xcalc_color:
X
X printf("\nAnalyzing data...");
X for(i=0; i!=twopowers[bmhd.nplanes]; colors_used[i++]=0);
X for(i=0; i!=bmhd.h; i++) {
X for(j=0; j!=bmhd.w; j++) {
X colors_used[get_a_bit(i,j)] = 1;
X }
X }
X
X/* Show the current color register stuff */
X
Xstart_over:
X
X printf("\nCurrent color register assignments for this picture are:\n");
X
X for(i=0; i!=twopowers[bmhd.nplanes]; i++) {
X if(colors_used[i]) {
X printf("%2d -> R:%2d G:%2d B:%2d ",
X i, Cmap[i*3]>>4, Cmap[i*3+1]>>4, Cmap[i*3+2]>>4);
X }
X else {
X printf("%2d -> Not Used ",i);
X }
X if(i&1) printf("\n");
X }
X
X/* Check to see if the user wants to change any of the register assignments.
X If so, do the appropriate transformations of the data base. */
X
X printf("\nDo you wish to change assignments (y or n)? ");
X do {
X tempbyte = getchar();
X }
X while( (tempbyte!='y')
X && (tempbyte!='Y')
X && (tempbyte!='n')
X && (tempbyte!='N'));
X
X if((tempbyte == 'y') || (tempbyte == 'Y')) {
X if(get_new_colors()) goto start_over; /* If invalid change, loop */
X printf("\nProcessing color change...");
X for(i=0; i!=96; old_cmap[i] = Cmap[i++]); /* Save old colors */
X for(i=0; i!=bmhd.h; i++) { /* lines */
X for(j=0; j!=bmhd.w; j++) { /* bits */
X temp = get_a_bit(i,j);
X if(tran_table[temp]!=-1) {
X put_a_bit(i,j,tran_table[temp]);
X for(k=0; k!=3; k++) { /* swap colors */
X Cmap[tran_table[temp]*3+k] = old_cmap[temp*3+k];
X }
X }
X }
X }
X goto calc_color; /* show the new arrangement */
X }
X
X/* Now, write the data to the output file, color map first, then data,
X plane by plane, line by line */
X
X printf("\nWriting output file...");
X
X/* Output a few statistics */
X
X fprintf(o_file, "/* Image %s */\n",argv[1]);
X fprintf(o_file, " Width: %d\n",bmhd.w);
X fprintf(o_file, " Height: %d\n",bmhd.h);
X fprintf(o_file, " Depth: %d */\n",bmhd.nplanes);
X
X/* Start with the color map */
X
X fprintf(o_file, "/* Color Map (xxxxxx = unused color) */\n\n");
X fprintf(o_file, "USHORT map[] = {\n");
X for(i=0; i!=twopowers[bmhd.nplanes]; i++) {
X fprintf(o_file, " ");
X if(colors_used[i])
X make_word((Cmap[i*3]<<4)+Cmap[i*3+1]+(Cmap[i*3+2]>>4), o_file);
X else fprintf(o_file, "xxxxxx");
X if(i!=twopowers[bmhd.nplanes]-1) fprintf(o_file, ",");
X fprintf(o_file, "\n");
X }
X fprintf(o_file, "};\n\n");
X
X/* Now, do the data */
X
X fprintf(o_file, "/* Image Data */\n\n");
X fprintf(o_file, "UWORD %s[%d] = {\n", argv[1], buff_size/2);
X for(i=0; i!=bmhd.nplanes; i++) {
X fprintf(o_file, "/* Bit Plane #%d */\n\n", i);
X for(j=0; j!=bmhd.h; j++) {
X fprintf(o_file, " ");
X buff_pointer = raster_lines[j][i];
X for(k=0; k<bytes_per_line; ) {
X tempbyte = *(buff_pointer+(k++));
X make_word((tempbyte << 8) | *(buff_pointer+(k++)), o_file);
X fprintf(o_file, ",");
X }
X fprintf(o_file, "\n");
X }
X fprintf(o_file, "\n");
X }
X fseek(o_file, -3, 1); /* back up to wipe out the last comma */
X fprintf(o_file, "\n};\n");
X
X/* Close up, clean up, and get out */
X
X fclose(o_file);
X fclose(i_file);
X printf("\n");
X FreeMem(buff_pointer_save, buff_size);
X}
X
X/* read_error - called if a read error occured */
X
Xread_error()
X{
X printf("\nRead error in input file, aborting\n");
X exit(20);
X}
X
X/* chkread - reads from input file, checking for errors */
X
Xchkread(ptr, size, fd)
XAPTR *ptr;
XWORD size;
XFILE *fd;
X{
X WORD readin;
X readin = fread(ptr, size, 1, fd);
X if(readin != 1) read_error();
X}
X
X/* expand_map - decompresses data compressed with the byte_run encoding
X scheme described in the IFF document. A signed byte, x,
X is read from the input block. If the signed value of x
X is negative, but not -128 ( 0x80 ), the next byte is read
X and is placed in the output block (-x+1) times. If the
X signed value is positive, the next (x+1) bytes are copied
X directly to the output block. If the signed value is -128,
X no operation is performed.
X*/
X
X
Xexpand_map(length, pointer, data_pointer)
XWORD length;
XUBYTE *pointer;
XUBYTE **data_pointer;
X{
X
X WORD minus128 = -128;
X WORD temp;
X BYTE tempbyte;
X UBYTE tempubyte;
X
X while( length > 0 ) {
X tempbyte = *((*data_pointer)++);
X temp = tempbyte;
X if (temp >= 0) {
X temp += 1;
X length-=temp;
X do {
X *(pointer++) = *((*data_pointer)++);
X }
X while (--temp > 0);
X }
X else if (temp != minus128) {
X temp = (-temp) + 1;
X length -= temp;
X tempubyte = *((*data_pointer)++);
X do {
X *(pointer++) = tempubyte;
X }
X while (--temp > 0);
X }
X }
X}
X
X/* get_a_bit - returns the color value of the bit at location x,y in the
X image.
X*/
X
Xget_a_bit(y, x)
XLONG y, x;
X{
X LONG xbyte, xbit,i;
X UBYTE tempbyte, color;
X UBYTE *pointer;
X
X color = 0; /* start with no color */
X xbyte =x>>3; /* xbyte = the byte location of x */
X xbit = (1<<(x&7)); /* xbit = the mask for the bit */
X for(i=0; i!=bmhd.nplanes; i++) { /* do all the planes */
X pointer = raster_lines[y][i]; /* get the base address */
X tempbyte = *(pointer + xbyte); /* get the proper byte */
X if(tempbyte & xbit) color |= (1 << i); /* OR in the color bit */
X }
X return color;
X}
X
X/* put_a_bit - sets a given bit to a given color */
X
Xput_a_bit(y, x, color)
XLONG y, x, color;
X{
X LONG xbyte, xbit, i;
X UBYTE *pointer;
X UBYTE tempbyte;
X
X for(i=0; i!=bmhd.nplanes; i++) {
X xbyte = x>>3;
X xbit = (1 << (x & 7));
X pointer = raster_lines[y][i];
X tempbyte = *(pointer + xbyte); /* get the appropriate byte */
X tempbyte &= 0xff-xbit; /* mask off the proper bit */
X if(color & twopowers[i]) { /* if the color bit is set, */
X tempbyte |= xbit; /* set the bit in the byte */
X }
X *(pointer + xbyte) = tempbyte; /* save the modified byte */
X }
X}
X
X/* get_new_colors - get the users choices for register assignments */
X
Xget_new_colors()
X{
X int i,j;
X
X for(i=0; i!=twopowers[bmhd.nplanes]; tran_table[i++]=-1); /* reset */
X for(i=1; i!=twopowers[bmhd.nplanes]; i++) {
X if(colors_used[i]) { /* for each color used in the original */
Xgetnew:
X printf("\nOld color register %2d (R:%2d G:%2d B:%2d) new number:",
X i, Cmap[i*3]>>4, Cmap[i*3+1]>>4, Cmap[i*3+2]>>4);
X scanf("%d", &j);
X if((j<1) || (j>=twopowers[bmhd.nplanes])) {
X printf("\nRegister number must be greater than zero, and less than %2d.",
X twopowers[bmhd.nplanes]);
X printf("\nTry again.");
X goto getnew;
X }
X tran_table[i] = j;
X }
X }
X
X/* Check the translation table for duplicated register assignments. */
X
X for(i=1; i!=twopowers[bmhd.nplanes]-1; i++) {
X for(j=i+1; j!=twopowers[bmhd.nplanes]; j++) {
X if((tran_table[i]==-1) || (tran_table[j]==-1)) continue;
X if(tran_table[i] == tran_table[j]) {
X printf("\nDuplicate color register assignment - try again.");
X return -1;
X }
X }
X }
X return 0;
X}
X
X/* make_word - outputs a string representing a four-digit hex number */
X
Xmake_word(num, fp)
XUWORD num;
XFILE *fp;
X{
X char temp[10];
X
X sprintf(temp, "0000%x\0", num);
X fprintf(fp, "0x%s", &temp[strlen(temp)-4]);
X}
SHAR_EOF
# End of shell archive
exit 0
------
--
Mike Farren
uucp: {your favorite backbone site}!hplabs!well!farren
Fido: Sci-Fido, Fidonode 125/84, (415)655-0667
More information about the Comp.sources.unix
mailing list