-/* rasttofish.c - read a Sun rasterfile and produce an xfish header file
-**
-** All code to read sun rasters came from rasttopnm, his copyright follows.
-**
-** Copyright (C) 1989, 1991 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation. This software is provided "as is" without express or
-** implied warranty.
-*/
-
-#ifdef __STDC__
-#define ARGS(alist) alist
-#else /*__STDC__*/
-#define ARGS(alist) ()
-#define const
-#endif /*__STDC__*/
-
-
-#include <stdio.h>
-#include "rast.h"
-
-#define MAXCOLORS 256
-#define DEFAULT_NAME "fish"
-
-struct rgb_color {
- unsigned int red, green, blue;
-};
-
-
-int
-pm_readbiglong(in, lP)
-FILE *in;
-long *lP;
-{
- int c;
-
- if ((c = getc(in)) == EOF)
- return -1;
- *lP = (c & 0xff) << 24;
- if ((c = getc(in)) == EOF)
- return -1;
- *lP |= (c & 0xff) << 16;
- if ((c = getc(in)) == EOF)
- return -1;
- *lP |= (c & 0xff) << 8;
- if ((c = getc(in)) == EOF)
- return -1;
- *lP |= c & 0xff;
- return 0;
-}
-
-int
-pr_load_header(in, hP)
-FILE *in;
-struct rasterfile *hP;
-{
- if (pm_readbiglong(in, &(hP->ras_magic)) == -1)
- return PIX_ERR;
- if (hP->ras_magic != RAS_MAGIC)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_width)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_height)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_depth)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_length)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_type)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_maptype)) == -1)
- return PIX_ERR;
- if (pm_readbiglong(in, &(hP->ras_maplength)) == -1)
- return PIX_ERR;
- return 0;
-}
-
-int
-pr_load_colormap(in, hP, colormap)
-FILE *in;
-struct rasterfile *hP;
-colormap_t *colormap;
-{
- if (colormap == NULL || hP->ras_maptype == RMT_NONE) {
- char junk[30000];
-
- if (fread(junk, 1, hP->ras_maplength, in) != hP->ras_maplength)
- return PIX_ERR;
- } else {
- colormap->type = hP->ras_maptype;
- switch (hP->ras_maptype) {
- case RMT_EQUAL_RGB:
- colormap->length = hP->ras_maplength / 3;
- colormap->map[0] = (unsigned char *) malloc(colormap->length);
- if (colormap->map[0] == NULL)
- return PIX_ERR;
- colormap->map[1] = (unsigned char *) malloc(colormap->length);
- if (colormap->map[1] == NULL) {
- free(colormap->map[0]);
- return PIX_ERR;
- }
- colormap->map[2] = (unsigned char *) malloc(colormap->length);
- if (colormap->map[2] == NULL) {
- free(colormap->map[0]);
- free(colormap->map[1]);
- return PIX_ERR;
- }
- if (fread(colormap->map[0], 1, colormap->length, in) != colormap->length ||
- fread(colormap->map[1], 1, colormap->length, in) != colormap->length ||
- fread(colormap->map[2], 1, colormap->length, in) != colormap->length) {
- free(colormap->map[0]);
- free(colormap->map[1]);
- free(colormap->map[2]);
- return PIX_ERR;
- }
- break;
-
- case RMT_RAW:
- colormap->length = hP->ras_maplength;
- colormap->map[0] = (unsigned char *) malloc(colormap->length);
- if (colormap->map[0] == NULL)
- return PIX_ERR;
- colormap->map[2] = colormap->map[1] = colormap->map[0];
- if (fread(colormap->map[0], 1, hP->ras_maplength, in) != hP->ras_maplength) {
- free(colormap->map[0]);
- return PIX_ERR;
- }
- break;
-
- default:
- fprintf(stderr, "unknown colormap type\n");
- exit(1);
- }
- }
- return 0;
-}
-
-
-struct pixrect *
-mem_create(w, h, depth)
-int w, h, depth;
-{
- struct pixrect *p;
- struct mpr_data *m;
-
- p = (struct pixrect *) malloc(sizeof(struct pixrect));
- if (p == NULL)
- return NULL;
- p->pr_ops = NULL;
- p->pr_size.x = w;
- p->pr_size.y = h;
- p->pr_depth = depth;
- m = p->pr_data = (struct mpr_data *) malloc(sizeof(struct mpr_data));
- if (m == NULL) {
- free(p);
- return NULL;
- }
- /* According to the documentation, linebytes is supposed to be rounded
- ** up to a longword (except on 386 boxes). However, this turns out
- ** not to be the case. In reality, all of Sun's code rounds up to
- ** a short, not a long.
- */
- m->md_linebytes = (w * depth + 15) / 16 * 2;
- m->md_offset.x = 0;
- m->md_offset.y = 0;
- m->md_flags = 0;
- m->md_image = (unsigned char *) malloc(m->md_linebytes * h);
- if (m->md_image == NULL) {
- free(m);
- free(p);
- return NULL;
- }
-
- return p;
-}
-
-
-void
-mem_free(p)
-struct pixrect *p;
-{
- free(p->pr_data->md_image);
- free(p->pr_data);
- free(p);
-}
-
-
-
-
-struct pixrect *
-pr_load_image(in, hP, colormap)
-FILE *in;
-struct rasterfile *hP;
-colormap_t *colormap;
-{
- struct pixrect *p;
- unsigned char *beimage;
- register unsigned char *bep;
- register unsigned char *bp;
- register unsigned char c;
- int i;
- register int j, count;
-
- p = mem_create(hP->ras_width, hP->ras_height, hP->ras_depth);
- if (p == NULL)
- return NULL;
-
- switch (hP->ras_type) {
- case RT_OLD:
- fprintf(stderr, "old rasterfile type is not supported\n");
- exit(1);
-
- case RT_FORMAT_TIFF:
- fprintf(stderr, "tiff rasterfile type is not supported\n");
- exit(1);
-
- case RT_FORMAT_IFF:
- fprintf(stderr, "iff rasterfile type is not supported\n");
- exit(1);
-
- case RT_EXPERIMENTAL:
- fprintf(stderr, "experimental rasterfile type is not supported\n");
- exit(1);
-
- case RT_STANDARD:
- case RT_FORMAT_RGB:
- /* Ignore hP->ras_length. */
- i = p->pr_size.y * p->pr_data->md_linebytes;
- if (fread(p->pr_data->md_image, 1, i, in) != i) {
- mem_free(p);
- return NULL;
- }
- break;
-
- case RT_BYTE_ENCODED:
- beimage = (unsigned char *) malloc(hP->ras_length);
- if (beimage == NULL) {
- mem_free(p);
- return NULL;
- }
- if (fread(beimage, 1, hP->ras_length, in) != hP->ras_length) {
- mem_free(p);
- free(beimage);
- return NULL;
- }
- bep = beimage;
- bp = p->pr_data->md_image;
- for (i = 0; i < hP->ras_length;) {
- c = *bep++;
- if (c == 128) {
- count = (*bep++) + 1;
- if (count == 1) {
- *bp++ = 128;
- i += 2;
- } else {
- c = *bep++;
- for (j = 0; j < count; ++j)
- *bp++ = c;
- i += 3;
- }
- } else {
- *bp++ = c;
- ++i;
- }
- }
- free(beimage);
- break;
-
- default:
- fprintf(stderr, "unknown rasterfile type\n");
- exit(1);
- }
-
- return p;
-}
-
-
-unsigned char *
-ReadRaster(ifp, w, h, colrs)
-FILE *ifp;
-int *w, *h;
-struct rgb_color *colrs;
-{
- struct rasterfile header;
- colormap_t pr_colormap;
- struct pixrect *pr;
- unsigned char *data;
- unsigned char *dptr;
- unsigned char *rdata;
- unsigned char *ptr;
- int linesize;
- int depth;
- int maxval;
- int i, j;
-
- /* Read in the rasterfile. First the header. */
- if (pr_load_header(ifp, &header) != 0) {
- fprintf(stderr, "unable to read in rasterfile header\n");
- exit(1);
- }
-
- *w = header.ras_width;
- *h = header.ras_height;
-
- depth = header.ras_depth;
-
- if (*w <= 0) {
- fprintf(stderr, "invalid width\n");
- exit(1);
- }
- if (*h <= 0) {
- fprintf(stderr, "invalid height\n");
- exit(1);
- }
-
- /* If there is a color map, read it. */
- if (header.ras_maplength != 0) {
- if (pr_load_colormap(ifp, &header, &pr_colormap) != 0) {
- fprintf(stderr, "no colormap\n");
- exit(1);
- }
- }
-
- /* Check the depth and color map. */
- switch (depth) {
- case 8:
- if (header.ras_maptype != RMT_EQUAL_RGB) {
- fprintf(stderr, "not an RGB colormap\n");
- exit(1);
- }
- maxval = 255;
- break;
- default:
- fprintf(stderr, "Can only handle depth 8 images\n");
- exit(1);
- }
-
- for (i = 0; i < maxval; i++) {
- colrs[i].red = pr_colormap.map[0][i];
- colrs[i].green = pr_colormap.map[1][i];
- colrs[i].blue = pr_colormap.map[2][i];
- }
-
- /* Now load the data. The pixrect returned is a memory pixrect. */
- if ((pr = pr_load_image(ifp, &header, NULL)) == NULL) {
- fprintf(stderr, "unable to read image from the rasterfile\n");
- exit(1);
- }
-
- linesize = ((struct mpr_data *) pr->pr_data)->md_linebytes;
- data = ((struct mpr_data *) pr->pr_data)->md_image;
-
- rdata = (unsigned char *) malloc((*w) * (*h));
- ptr = rdata;
- for (j = 0; j < (*h); j++) {
- dptr = (unsigned char *) data;
- for (i = 0; i < (*w); i++) {
- *ptr++ = *dptr++;
- }
- data += linesize;
- }
- return (rdata);
-}
-
-
-struct rgb_color
- *
-MapColors(data1, colrs1, data2, colrs2, width, height, Cnt)
-unsigned char *data1;
-struct rgb_color *colrs1;
-unsigned char *data2;
-struct rgb_color *colrs2;
-int width, height;
-int *Cnt;
-{
- int i, j;
- int fcnt, indx;
- int Mapping[MAXCOLORS];
- unsigned char *ptr;
- struct rgb_color *fcolrs;
-
- fcolrs = (struct rgb_color *) malloc((MAXCOLORS + 1) * sizeof(struct rgb_color));
-
- fcnt = 0;
- ptr = data1;
- for (i = 0; i < (width * height); i++) {
- indx = (int) *ptr;
- for (j = 0; j < fcnt; j++) {
- if ((fcolrs[j].red == colrs1[indx].red) &&
- (fcolrs[j].green == colrs1[indx].green) &&
- (fcolrs[j].blue == colrs1[indx].blue)) {
- break;
- }
- }
- if (j == fcnt) {
- fcolrs[j].red = colrs1[indx].red;
- fcolrs[j].green = colrs1[indx].green;
- fcolrs[j].blue = colrs1[indx].blue;
- Mapping[indx] = j;
- fcnt++;
- if (fcnt > MAXCOLORS) {
- fprintf(stderr, "Error: cannot use more than %d colors in your fish\n",
- MAXCOLORS);
- exit(1);
- }
- }
- ptr++;
- }
- ptr = data1;
- for (i = 0; i < (width * height); i++) {
- indx = (int) *ptr;
- *ptr = (unsigned char) (Mapping[indx]);
- ptr++;
- }
-
- ptr = data2;
- for (i = 0; i < (width * height); i++) {
- indx = (int) *ptr;
- for (j = 0; j < fcnt; j++) {
- if ((fcolrs[j].red == colrs2[indx].red) &&
- (fcolrs[j].green == colrs2[indx].green) &&
- (fcolrs[j].blue == colrs2[indx].blue)) {
- break;
- }
- }
- if (j == fcnt) {
- fcolrs[j].red = colrs2[indx].red;
- fcolrs[j].green = colrs2[indx].green;
- fcolrs[j].blue = colrs2[indx].blue;
- Mapping[indx] = j;
- fcnt++;
- if (fcnt > MAXCOLORS) {
- fprintf(stderr, "Error: cannot use more than %d colors in your fish\n",
- MAXCOLORS);
- exit(1);
- }
- }
- ptr++;
- }
- ptr = data2;
- for (i = 0; i < (width * height); i++) {
- indx = (int) *ptr;
- *ptr = (unsigned char) (Mapping[indx]);
- ptr++;
- }
-
- for (i = 0; i < fcnt; i++) {
- fcolrs[i].red = fcolrs[i].red * 256;
- fcolrs[i].green = fcolrs[i].green * 256;
- fcolrs[i].blue = fcolrs[i].blue * 256;
- }
- for (i = fcnt; i < 16; i++) {
- fcolrs[i].red = 0;
- fcolrs[i].green = 0;
- fcolrs[i].blue = 0;
- }
-
- if (fcnt < 16) {
- fcnt = 16;
- }
- *Cnt = fcnt;
- return (fcolrs);
-}
-
-
-main(argc, argv)
-int argc;
-char *argv[];
-{
- FILE *ifp;
- FILE *ofd;
- int i, j, cnt, fcnt;
- struct rgb_color colrs1[MAXCOLORS];
- struct rgb_color colrs2[MAXCOLORS];
- struct rgb_color *fcolrs;
- unsigned char *data;
- unsigned char *ptr, *ptr1, *ptr2;
- unsigned char *data1, *data2;
- int width1, height1, width2, height2;
- char outfile[256];
- char *outname;
-
- ifp = NULL;
- if (argc > 1) {
- ifp = fopen(argv[1], "r");
- }
- if (ifp == NULL) {
- ifp = stdin;
- }
-
- data = ReadRaster(ifp, &width1, &height1, colrs1);
-
- /* Mirror around Y axis, and copy */
- for (i = 0; i < MAXCOLORS; i++) {
- colrs2[i].red = colrs1[i].red;
- colrs2[i].green = colrs1[i].green;
- colrs2[i].blue = colrs1[i].blue;
- }
- width2 = width1;
- height2 = height1;
- data1 = (unsigned char *) malloc(width1 * height1);
- data2 = (unsigned char *) malloc(width1 * height1);
- ptr1 = data1;
- ptr2 = data2;
- for (j = 0; j < height1; j++) {
- ptr = (unsigned char *) (data + ((j + 1) * width1) - 1);
- for (i = 0; i < width1; i++) {
- *ptr1++ = *ptr;
- *ptr2++ = *ptr;
- ptr--;
- }
- }
-
- fcolrs = MapColors(data1, colrs1, data2, colrs2, width1, height1, &fcnt);
-
- if (argc > 2) {
- outname = argv[2];
- } else {
- cnt = 0;
- if (argc > 1) {
- while ((argv[1][cnt] != '.') && (argv[1][cnt] != '\0')) {
- cnt++;
- }
- }
- if (cnt == 0) {
- outname = (char *) malloc(strlen(DEFAULT_NAME) + 1);
- strcpy(outname, DEFAULT_NAME);
- } else {
- outname = (char *) malloc(cnt + 1);
- strncpy(outname, argv[1], cnt);
- outname[cnt] = '\0';
- }
- }
- sprintf(outfile, "%s.h", outname);
-
- ofd = fopen(outfile, "w");
- if (ofd == NULL) {
- fprintf(stderr, "Error: cannot open (%s) for writing\n", outfile);
- exit(1);
- }
-
- fprintf(ofd, "#define %s_width\t\t%d\n", outname, width1);
- fprintf(ofd, "#define %s_height\t\t%d\n", outname, height1);
- fprintf(ofd, "#define %s_colors\t\t%d\n", outname, fcnt);
- fprintf(ofd, "#define %s_back\t\t%d\n", outname, (int) data1[0]);
- fprintf(ofd, "int\t%s_reds[] = {", outname);
- for (i = 0; i < fcnt; i++) {
- if (i == (fcnt - 1)) {
- fprintf(ofd, "%d};\n", fcolrs[i].red);
- } else {
- fprintf(ofd, "%d, ", fcolrs[i].red);
- }
- }
- fprintf(ofd, "int\t%s_greens[] = {", outname);
- for (i = 0; i < fcnt; i++) {
- if (i == (fcnt - 1)) {
- fprintf(ofd, "%d};\n", fcolrs[i].green);
- } else {
- fprintf(ofd, "%d, ", fcolrs[i].green);
- }
- }
- fprintf(ofd, "int\t%s_blues[] = {", outname);
- for (i = 0; i < fcnt; i++) {
- if (i == (fcnt - 1)) {
- fprintf(ofd, "%d};\n", fcolrs[i].blue);
- } else {
- fprintf(ofd, "%d, ", fcolrs[i].blue);
- }
- }
- fprintf(ofd, "unsigned char\t%s_rasterA[] = {\n", outname);
- for (i = 0; i < (width1 * height1); i++) {
- fprintf(ofd, "0x%02x,", data1[i]);
- }
- fprintf(ofd, "};\n");
- fprintf(ofd, "unsigned char\t%s_rasterB[] = {\n", outname);
- for (i = 0; i < (width1 * height1); i++) {
- fprintf(ofd, "0x%02x,", data2[i]);
- }
- fprintf(ofd, "};\n");
-
- fclose(ofd);
-
- exit(0);
-}