farren@well.UUCP (02/02/86)
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