home *** CD-ROM | disk | FTP | other *** search
- /*
- * Writeilbm.c
- *
- * Writes out a 24 bit IFF ILBM file, compressed or uncompressed from a 24 or 32 bit
- * Sun Raster file.
- * By Brett Van Sprewenburg
- *
- * A nice addition would be to convert regular 8 bit rasters to 24 bit, then write the ilbm.
- * (see version 1.4, hehe)
- *
- * Credit to the ppm utilities, the developer(s) of xv, and Commodore-Amiga for
- * code and ideas.
- *
- * Version
- * 1.0 2/1/93 First working version, with hardcoded form and body chunk sizes.
- * Only uncompressed images work.
- * 1.1 2/2/93 Added in the correct form and body sizes with compression by altering
- * the file after it was written.
- *
- * 1.2 2/4/93 First working version with compression done correctly. I still wouldn't
- * be able to tell you exactly what was wrong. Fixed multiple things with
- * readilbm integration. The biggest problem with this version is that it's sloooow.
- * A faster way may be to do 8 planes at once, instead of a plane at a time.
- * 1.3 2/9/93 Fixed previous slowness by compiling with acc -fast. ANIS'fied code also for
- * compilation with acc without warnings.
- * 1.4 2/10/93 Added reading and conversion of 8 bit rasters into 24 bit ilbms.
- * 1.4.1 2/12/93 Checked that memeory allocations succeded.
- * First public release.
- */
-
- #include <writeilbm.h>
-
- int WriteILBM(char *, int);
-
- extern byte *pic; /* Pointer to pixel interleaved raster */
- /* Or index into cmap if < 24 bit planes */
- extern byte r[255],g[255],b[255]; /* Said cmap */
-
- int WriteILBM(char *ilbmfile, int compression)
- {
- FILE *fp;
- long formsize,bmhdsize,bodysize;
- byte *coded_rowbuf,*cp,*raw_rowbuf;
- int rel_count,rgbline,linesize,mask,yoffset,offset,push;
- register int row, col, plane;
- unsigned int bit;
- static byte *image,*hpic,*ebitimage,*tpic;
- int pad,tot_bytes,packedbytes,ycoffset,coffset,ccol = 0;
-
- tot_bytes = packedbytes = 0;
-
- if ((fp = fopen(ilbmfile,"w")) == NULL) {
- fprintf(stderr,"Open of '%s' for writing failed.\n",ilbmfile);
- return -1;
- }
-
- /* I'm fairly certain that I can't handle an odd sized bitmap, so I'll just turn 'em away */
- if ((sunheader.ras_width % 8) != 0) {
- fprintf(stderr,"Width of '%d' is not gonna work. Must be multiple of 8.\n",sunheader.ras_width);
- fclose(fp);
- return -1;
- }
-
- if (sunheader.ras_depth < 24) { /* Convert 8 to 24 bits */
- if (sunheader.ras_maptype != RMT_EQUAL_RGB) {
- fprintf(stderr,"Unknown colormap type. Save from 'xv' and try again.\n");
- fclose(fp);
- return -1;
- }
- tpic = pic;
- fprintf(stderr,"Converting Sun Raster to 24 bit planes.\n");
- hpic = (byte *)malloc(sunheader.ras_height * sunheader.ras_width * 3);
- if (hpic == NULL) {
- fprintf(stderr,"Can't get the memory I need...\n");
- fclose(fp);
- return -2;
- }
- ebitimage = hpic;
-
- for (row = 0; row < (int)sunheader.ras_height; row++) {
- yoffset = row * sunheader.ras_width;
- ycoffset = row * (sunheader.ras_width * 3);
- for (col = 0; col < (int)sunheader.ras_width; col++) {
- offset = yoffset + col;
- coffset = ycoffset + ccol;
- *(hpic + coffset) = r[*(tpic + offset)];
- coffset++;
- *(hpic + coffset) = g[*(tpic + offset)];
- coffset++;
- *(hpic + coffset) = b[*(tpic + offset)];
- ccol+=3;
- if (ccol == (sunheader.ras_width * 3))
- ccol = 0;
- }
- }
- pic = ebitimage;
- }
-
- /* Assign information to ilbm header */
- /* See AmigaDOS hardware RKM for more info */
- ilbmheader.w = (unsigned short)sunheader.ras_width;
- ilbmheader.h = (unsigned short)sunheader.ras_height;
- ilbmheader.x = 0;
- ilbmheader.y = 0;
- ilbmheader.nPlanes = 24; /* We're only going to write 24 bit IFF's */
- ilbmheader.masking = mskNone;
- if (compression) {
- ilbmheader.compression = cmpByteRun1;
- printf("Compression On.\n");
- } else
- ilbmheader.compression = cmpNone;
- ilbmheader.pad1 = 0;
- ilbmheader.transparentColor = 0;
- ilbmheader.xAspect = 10;
- ilbmheader.yAspect = 10;
- ilbmheader.pageWidth = (unsigned short)sunheader.ras_width ;
- ilbmheader.pageHeight = (unsigned short)sunheader.ras_height;
-
- /* Full pixel interleaved line consists of tuplets of rgb values */
- rgbline = ilbmheader.w * 3;
- coded_rowbuf = (byte *)malloc(ilbmheader.w);
- raw_rowbuf = (byte *)malloc(rgbline);
- if (coded_rowbuf == NULL || raw_rowbuf == NULL) {
- fprintf(stderr,"Can't get the memory I need...\n");
- fclose(fp);
- return -2;
- }
-
- /* RoyBytes fromula from ilbm.h */
- linesize = RowBytes(ilbmheader.w);
- bmhdsize = sizeof(struct BitMapHeader);
- if (!compression) {
- bodysize = ilbmheader.h * linesize * ilbmheader.nPlanes;
- formsize = 4 + 4 + 4 + bmhdsize + 4 + 4 + bodysize;
- } else {
- bodysize = 999999;
- formsize = 999999; /* Do this because we don't know how much compression we'll get */
- }
-
- fwrite("FORM",4,1,fp);
- fwrite(&formsize,4,1,fp);
- fwrite("ILBM",4,1,fp);
- fwrite("BMHD",4,1,fp);
- fwrite(&bmhdsize,4,1,fp);
- fwrite(&ilbmheader,bmhdsize,1,fp);
- fwrite("BODY",4,1,fp);
- fwrite(&bodysize,4,1,fp);
-
- image = raw_rowbuf; /* Hold this pointer to the raw buffer in image pointer */
-
- /* This next whole thing took quite a while to figure out
- This file format looks like this: ( all data is bit reversed )
- Plane data scanline
- -------------------------------------------
- Plane 0: RowBytes of red 0
- Plane 1: RowBytes of red 0
- |
- Plane 7: RowBytes of red 0
- Plane 8: RowBytes of green 0
- |
- Plane 15: RowBytes of green 0
- Plane 16: RowBytes of blue 0
- |
- Plane 23: RowBytes of blue 0
- Plane 0: RowBytes of red 1
- Plane 1: RowBytes of red 1
- and the beat goes on...
- */
-
- /* Figure this next bit out for yourself :-< */
-
- for (row = 0;row < (int)ilbmheader.h;row++) {
- yoffset = row * rgbline;
- raw_rowbuf = image;
- for (plane = 0 ;plane < (int)ilbmheader.nPlanes; plane++) {
- if (plane < 8) {
- push = plane;
- } else if (plane > 15) {
- push = plane - 16;
- }
- else {
- push = plane - 8;
- }
- mask = 1 << push; /* how many bits to push */
- cp = coded_rowbuf;
- *cp = 0;
- for (col = (plane / 8), rel_count = 0 ; col < rgbline; rel_count++ ,col+=3) {
- offset = yoffset + col;
- bit = (*(pic + offset) & mask) ? 1 : 0;
- *cp |= bit << ( 7 - (rel_count % 8) );
- if ((rel_count % 8) == 7) { /* Every 8th byte, advance pixel */
- cp++;
- *cp = 0;
- }
- }
- if (compression) { /* This bit is pretty obvious. */
- raw_rowbuf = image; /* compression is rle, as specified in AmigaDOS 2.0 RKM */
- packedbytes = packrow(coded_rowbuf, raw_rowbuf, linesize);
- tot_bytes+=packedbytes;
- fwrite(raw_rowbuf, packedbytes, 1, fp);
- } else /* Write uncompressed data */
- fwrite(coded_rowbuf, linesize, 1, fp);
- }
- }
- if (compression) {
- fclose(fp); /* close because we must alter the fopen flags */
- if ((fp = fopen(ilbmfile,"r+")) == NULL) {
- fprintf(stderr,"Open of '%s' for rewriting failed.\n",ilbmfile);
- return -1; /* Hack in the real bodysize and formsize values */
- }
- formsize = tot_bytes + ILBMHSIZE;/* 40 is the number of bytes in the header after FORM and size */
- fseek(fp,4L,0);
- fwrite(&formsize,4,1,fp);
- fseek(fp,44L,0);
- fwrite(&tot_bytes,4,1,fp);
- }
- if ((tot_bytes % 2) != 0) { /* Pad the body chunk out to an even byte */
- fseek(fp,0L,2);
- pad = 0;
- fwrite(&pad,1,1,fp);
- }
- fclose(fp);
- free(coded_rowbuf);
- free(raw_rowbuf);
- return 0;
- }
-