#define _GNU_SOURCE #include #include "Imlib.h" #include "Imlib_private.h" #include /* Split the ID - damages input */ static char * _SplitID(char *file) { #ifndef __EMX__ char *p = strrchr(file, ':'); #else char *p = strrchr(file, ';'); #endif if (p == NULL) return ""; else { *p++ = 0; return p; } } /* * * Doesn't damage the input */ char * _GetExtension(char *file) { char *p = strrchr(file, '.'); if (p == NULL) return ""; else return p + 1; } /* * Make sure we don't wrap on our memory allocations */ void * _imlib_malloc_image(unsigned int w, unsigned int h) { if( w > 32767 || h > 32767) return NULL; return malloc(w * h * 3); } #ifdef HAVE_LIBJPEG /** * * This error handling is broken beyond belief, but oh well it works * **/ struct ImLib_JPEG_error_mgr { struct jpeg_error_mgr pub; sigjmp_buf setjmp_buffer; }; typedef struct ImLib_JPEG_error_mgr *emptr; void _JPEGFatalErrorHandler(j_common_ptr cinfo) { /* * FIXME: * We should somehow signal what error occurred to the caller so the * caller can handle the error message */ emptr errmgr; errmgr = (emptr) cinfo->err; cinfo->err->output_message(cinfo); siglongjmp(errmgr->setjmp_buffer, 1); return; } unsigned char * _LoadJPEG(ImlibData * id, FILE * f, int *w, int *h) { struct jpeg_decompress_struct cinfo; struct ImLib_JPEG_error_mgr jerr; unsigned char *data, *line[16], *ptr; int x, y, i; cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; /* error handler to longjmp to, we want to preserve signals */ if (sigsetjmp(jerr.setjmp_buffer, 1)) { /* Whoops there was a jpeg error */ jpeg_destroy_decompress(&cinfo); return NULL; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); *w = cinfo.output_width; *h = cinfo.output_height; data = _imlib_malloc_image(*w, *h); if (!data) { jpeg_destroy_decompress(&cinfo); return NULL; } ptr = data; if (cinfo.rec_outbuf_height > 16) { fprintf(stderr, "Imlib ERROR: JPEG uses line buffers > 16. Cannot load.\n"); return NULL; } if (cinfo.output_components == 3) { for (y = 0; y < *h; y += cinfo.rec_outbuf_height) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { line[i] = ptr; ptr += *w * 3; } jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); } } else if (cinfo.output_components == 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { if ((line[i] = malloc(*w)) == NULL) { int t = 0; for (t = 0; t < i; t++) free(line[t]); jpeg_destroy_decompress(&cinfo); return NULL; } } for (y = 0; y < *h; y += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); for (i = 0; i < cinfo.rec_outbuf_height; i++) { for (x = 0; x < *w; x++) { *ptr++ = line[i][x]; *ptr++ = line[i][x]; *ptr++ = line[i][x]; } } } for (i = 0; i < cinfo.rec_outbuf_height; i++) free(line[i]); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return data; } #endif /* HAVE_LIBJPEG */ #ifdef HAVE_LIBPNG unsigned char * _LoadPNG(ImlibData * id, FILE * f, int *w, int *h, int *t) { png_structp png_ptr; png_infop info_ptr; unsigned char *data, *ptr, **lines, *ptr2, r, g, b, a; int i, x, y, transp, bit_depth, color_type, interlace_type; png_uint_32 ww, hh; /* Init PNG Reader */ transp = 0; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return NULL; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } png_init_io(png_ptr, f); /* Read Header */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &ww, &hh, &bit_depth, &color_type, &interlace_type, NULL, NULL); *w = ww; *h = hh; /* Setup Translators */ if ((color_type == PNG_COLOR_TYPE_PALETTE) || (color_type == PNG_COLOR_TYPE_GRAY)) png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_packing(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); data = _imlib_malloc_image(*w, *h); if (!data) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } /* This malloc is fine, _imlib_malloc_image will fail first */ lines = (unsigned char **)malloc(*h * sizeof(unsigned char *)); if (lines == NULL) { free(data); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } for (i = 0; i < *h; i++) { /* Safe as well for the same reason as above */ if ((lines[i] = malloc(*w * (sizeof(unsigned char) * 4))) == NULL) { int n; free(data); for (n = 0; n < i; n++) free(lines[n]); free(lines); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } } png_read_image(png_ptr, lines); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); ptr = data; if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { for (y = 0; y < *h; y++) { ptr2 = lines[y]; for (x = 0; x < *w; x++) { r = *ptr2++; a = *ptr2++; if (a < 128) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; transp = 1; } else { *ptr++ = r; *ptr++ = r; *ptr++ = r; } } } } else if (color_type == PNG_COLOR_TYPE_GRAY) { for (y = 0; y < *h; y++) { ptr2 = lines[y]; for (x = 0; x < *w; x++) { r = *ptr2++; ptr2++; *ptr++ = r; *ptr++ = r; *ptr++ = r; } } } else { for (y = 0; y < *h; y++) { ptr2 = lines[y]; for (x = 0; x < *w; x++) { r = *ptr2++; g = *ptr2++; b = *ptr2++; a = *ptr2++; if (a < 128) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; transp = 1; } else { if ((r == 255) && (g == 0) && (b == 255)) r = 254; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } } for (i = 0; i < *h; i++) free(lines[i]); free(lines); *t = transp; return data; } #endif /* HAVE_LIBPNG */ #ifdef HAVE_LIBTIFF unsigned char * _LoadTIFF(ImlibData * id, FILE *f, char *file, int *w, int *h, int *t) { TIFF *tif; unsigned char *data, *ptr, r, g, b, a; int x, y; uint32 ww, hh, *rast, *tptr; size_t npix; int istransp; int fd; istransp = 0; if (!f) return NULL; fd = fileno(f); /* Apparently rewind(f) isn't sufficient */ lseek(fd, (long) 0, 0); /* So why does libtif need a filename here ??? */ tif = TIFFFdOpen(fd, file, "r"); if (!tif) return NULL; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &ww); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &hh); npix = ww * hh; *w = (int)ww; *h = (int)hh; if(ww > 32767 || hh > 32767) { TIFFClose(tif); return NULL; } rast = (uint32 *) _TIFFmalloc(npix * sizeof(uint32)); if (!rast) { TIFFClose(tif); return NULL; } data = NULL; if (TIFFReadRGBAImage(tif, ww, hh, rast, 0)) { data = (unsigned char *)malloc(*w ** h * 3); if (!data) { _TIFFfree(rast); TIFFClose(tif); return NULL; } ptr = data; for (y = 0; y < *h; y++) { tptr = rast; tptr += ((*h - y - 1) ** w); for (x = 0; x < *w; x++) { a = TIFFGetA(*tptr); b = TIFFGetB(*tptr); g = TIFFGetG(*tptr); r = TIFFGetR(*tptr); tptr++; if (a < 128) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; istransp = 1; } else { if ((r == 255) && (g == 0) && (b == 255)) r = 254; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } } _TIFFfree(rast); TIFFClose(tif); *t = istransp; return data; } #endif /* HAVE_LIBTIFF */ #ifdef HAVE_LIBGIF unsigned char * _LoadGIF(ImlibData * id, FILE *f, int *w, int *h, int *t) { unsigned char *data, *ptr; GifFileType *gif; GifRowType *rows; GifRecordType rec; ColorMapObject *cmap; int i, j, done, bg, csize, r, g, b; int intoffset[] = {0, 4, 2, 1}; int intjump[] = {8, 8, 4, 2}; int istransp, transp; int fd; done = 0; istransp = 0; data = NULL; rows = NULL; transp = -1; fd = fileno(f); /* Apparently rewind(f) isn't sufficient */ lseek(fd, (long) 0, 0); gif = DGifOpenFileHandle(fd); if (!gif) return NULL; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { PrintGifError(); rec = TERMINATE_RECORD_TYPE; } if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done)) { if (DGifGetImageDesc(gif) == GIF_ERROR) { PrintGifError(); rec = TERMINATE_RECORD_TYPE; } *w = gif->Image.Width; *h = gif->Image.Height; if (*h > 32767 || *w > 32767) { return NULL; } rows = malloc(*h * sizeof(GifRowType *)); if (!rows) { DGifCloseFile(gif); return NULL; } data = _imlib_malloc_image(*w, *h); if (!data) { DGifCloseFile(gif); free(rows); return NULL; } for (i = 0; i < *h; i++) rows[i] = NULL; for (i = 0; i < *h; i++) { rows[i] = malloc(*w * sizeof(GifPixelType)); if (!rows[i]) { DGifCloseFile(gif); for (i = 0; i < *h; i++) if (rows[i]) free(rows[i]); free(rows); free(data); return NULL; } } if (gif->Image.Interlace) { for (i = 0; i < 4; i++) { for (j = intoffset[i]; j < *h; j += intjump[i]) DGifGetLine(gif, rows[j], *w); } } else { for (i = 0; i < *h; i++) DGifGetLine(gif, rows[i], *w); } done = 1; } else if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext; ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0)) { istransp = 1; transp = (int)ext[4]; } ext = NULL; DGifGetExtensionNext(gif, &ext); } } } while (rec != TERMINATE_RECORD_TYPE); bg = gif->SBackGroundColor; cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap); csize = cmap->ColorCount; ptr = data; if (!istransp) { for (i = 0; i < *h; i++) { for (j = 0; j < *w; j++) { r = cmap->Colors[rows[i][j]].Red; g = cmap->Colors[rows[i][j]].Green; b = cmap->Colors[rows[i][j]].Blue; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } else { for (i = 0; i < *h; i++) { for (j = 0; j < *w; j++) { if (rows[i][j] == transp) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; } else { r = cmap->Colors[rows[i][j]].Red; g = cmap->Colors[rows[i][j]].Green; b = cmap->Colors[rows[i][j]].Blue; if ((r == 255) && (g == 0) && (b == 255)) r = 254; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } } DGifCloseFile(gif); for (i = 0; i < *h; i++) free(rows[i]); free(rows); *t = istransp; return data; } #endif /* HAVE_LIBGIF */ unsigned char * _LoadBMP(ImlibData * id, FILE *file, int *w, int *h, int *t) { unsigned char *data, *ptr; int done, i, bpp, planes, comp, ncolors, line, column, linesize, linepos, rshift, gshift, bshift, size; unsigned char byte; short int word; long int dbuf[4], dword, rmask, gmask, bmask, offset; signed char bbuf[4]; struct _cmap { unsigned char r, g, b; } *cmap; #define BI_RGB 0 #define BI_RLE8 1 #define BI_RLE4 2 #define BI_BITFIELDS 3 rshift = 0; gshift = 0; bshift = 0; rmask = 0xff; gmask = 0xff; bmask = 0xff; if (!file) return NULL; done = 0; /* * reading the bmp header */ fread(bbuf, 1, 2, file); fread(dbuf, 4, 4, file); size = dbuf[0]; offset = dbuf[2]; fread(dbuf, 4, 2, file); *w = (int)dbuf[0]; *h = (int)dbuf[1]; if ((*w > 32767) || (*w < 0)) { fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n"); return NULL; } if ((*h > 32767) || (*h < 0)) { fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n"); return NULL; } fread(&word, 2, 1, file); planes = (int)word; fread(&word, 2, 1, file); bpp = (int)word; if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32) { fprintf(stderr, "IMLIB ERROR: unknown bitdepth in file\n"); return NULL; } fread(dbuf, 4, 4, file); comp = (int)dbuf[0]; if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS) { fprintf(stderr, "IMLIB ERROR: unknown encoding in Windows BMP file\n"); return NULL; } fread(dbuf, 4, 2, file); ncolors = (int)dbuf[0]; if ((ncolors > (1 << bpp)) || (ncolors < 0)) ncolors = 1 << bpp; if ((ncolors < 0) || (ncolors > (1 << bpp))) ncolors = 1 << bpp; /* some more sanity checks */ if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32))) { fprintf(stderr, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n"); return NULL; } if (bpp < 16) { cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors); if (!cmap) { fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n"); return NULL; } } else cmap = NULL; ptr = (unsigned char *)_imlib_malloc_image(*w, *h); if (!ptr) { fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n"); if (cmap) free(cmap); return NULL; } /* * Reading the palette, if it exists. */ if (bpp < 16 && ncolors != 0) { for (i = 0; i < ncolors; i++) { fread(bbuf, 1, 4, file); cmap[i].b = bbuf[0]; cmap[i].g = bbuf[1]; cmap[i].r = bbuf[2]; } } else if (bpp == 16 || bpp == 32) { if (comp == BI_BITFIELDS) { int bit = 0; fread(dbuf, 4, 3, file); bmask = dbuf[0]; gmask = dbuf[1]; rmask = dbuf[2]; /* find shift amount.. ugly, but i can't think of a better way */ for (bit = 0; bit < bpp; bit++) { if (bmask & (1 << bit)) bshift = bit; if (gmask & (1 << bit)) gshift = bit; if (rmask & (1 << bit)) rshift = bit; } } else if (bpp == 16) { rmask = 0x7C00; gmask = 0x03E0; bmask = 0x001F; rshift = 10; gshift = 5; bshift = 0; } else if (bpp == 32) { rmask = 0x00FF0000; gmask = 0x0000FF00; bmask = 0x000000FF; rshift = 16; gshift = 8; bshift = 0; } } /* * Reading the image data */ fseek(file, offset, SEEK_SET); data = ptr; /* set the whole image to the background color */ if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8)) { for (i = 0; i < *w * *h; i++) { *ptr++ = cmap[0].r; *ptr++ = cmap[0].g; *ptr++ = cmap[0].b; } ptr = data; } line = 0; column = 0; #define poffset (line * *w * 3 + column * 3) /* * BMPs are stored upside down... hmmmmmmmmmm.... */ linesize = ((*w * bpp + 31) / 32) * 4; for (line = (*h - 1); line >= 0; line--) { linepos = 0; for (column = 0; column < *w;) { if (bpp < 16) { int index; linepos++; byte = getc(file); if (bpp == 1) { int bit = 0; for (bit = 0; bit < 8; bit++) { index = ((byte & (0x80 >> bit)) ? 1 : 0); /* possibly corrupted file? */ if (index < ncolors && poffset < *w * *h * 3) { ptr[poffset] = cmap[index].r; ptr[poffset + 1] = cmap[index].g; ptr[poffset + 2] = cmap[index].b; } column++; } } else if (bpp == 4) { if (comp == BI_RLE4) { fprintf(stderr, "can't deal with 4bit encoded yet.\n"); free(data); free(cmap); return NULL; } else { int nibble = 0; for (nibble = 0; nibble < 2; nibble++) { index = ((byte & (0xF0 >> nibble * 4)) >> (!nibble * 4)); if (index >= 16) index = 15; /* possibly corrupted file? */ if (index < ncolors && poffset < *w * *h * 3) { ptr[poffset] = cmap[index].r; ptr[poffset + 1] = cmap[index].g; ptr[poffset + 2] = cmap[index].b; } column++; } } } else if (bpp == 8) { if (comp == BI_RLE8) { unsigned char first = byte; byte = getc(file); if (first == 0) { if (byte == 0) { /* column = *w; */ } else if (byte == 1) { column = *w; line = -1; } else if (byte == 2) { byte = getc(file); column += byte; linepos = column * bpp / 8; byte = getc(file); line += byte; } else { int absolute = byte; for (i = 0; i < absolute; i++) { linepos++; byte = getc(file); /* possibly corrupted file? */ if (byte < ncolors && poffset < *w * *h * 3) { ptr[poffset] = cmap[byte].r; ptr[poffset + 1] = cmap[byte].g; ptr[poffset + 2] = cmap[byte].b; } column++; } if (absolute & 0x01) byte = getc(file); } } else { for (i = 0; i < first; i++) { /* possibly corrupted file? */ if (byte < ncolors && poffset < *w * *h * 3) { ptr[poffset] = cmap[byte].r; ptr[poffset + 1] = cmap[byte].g; ptr[poffset + 2] = cmap[byte].b; } column++; linepos++; } } } else { /* possibly corrupted file? */ if (byte < ncolors && poffset < *w * *h * 3) { ptr[poffset] = cmap[byte].r; ptr[poffset + 1] = cmap[byte].g; ptr[poffset + 2] = cmap[byte].b; } column++; } } } else if (bpp == 24) { linepos += fread(bbuf, 1, 3, file); /* possibly corrupted file? */ if (poffset < *w * *h * 3) { ptr[poffset] = (unsigned char)bbuf[2]; ptr[poffset + 1] = (unsigned char)bbuf[1]; ptr[poffset + 2] = (unsigned char)bbuf[0]; } column++; } else if (bpp == 16) { unsigned char temp; linepos += fread(&word, 2, 1, file); /* possibly corrupted file? */ if (poffset < *w * *h * 3) { temp = (word & rmask) >> rshift; ptr[poffset] = temp; temp = (word & gmask) >> gshift; ptr[poffset + 1] = temp; temp = (word & bmask) >> gshift; ptr[poffset + 2] = temp; } column++; } else { unsigned char temp; linepos += fread(&dword, 4, 1, file); /* possibly corrupted file? */ if (poffset < *w * *h * 3) { temp = (dword & rmask) >> rshift; ptr[poffset] = temp; temp = (dword & gmask) >> gshift; ptr[poffset + 1] = temp; temp = (dword & bmask) >> bshift; ptr[poffset + 2] = temp; } column++; } } while ((linepos < linesize) && (comp != 1) && (comp != 2)) { int temp = fread(&byte, 1, 1, file); linepos += temp; if (!temp) break; } } if (cmap) free(cmap); *t = 0; return data; } unsigned char * _LoadXPM(ImlibData * id, FILE *file, int *w, int *h, int *t) { unsigned char *data, *ptr, *end; int pc, c, i, j, k, ncolors, cpp, comment, transp, quote, context, len, done; char *line, s[256], tok[128], col[256]; XColor xcol; int lsz = 256; struct _cmap { unsigned char str[6]; unsigned char transp; short r, g, b; } *cmap; short lookup[128 - 32][128 - 32]; transp = 0; done = 0; if (!file) return NULL; i = 0; j = 0; cmap = NULL; *w = 10; *h = 10; ptr = NULL; data = NULL; end = NULL; c = ' '; comment = 0; quote = 0; context = 0; line = malloc(lsz); while (!done) { pc = c; c = fgetc(file); if (c == EOF) break; if (!quote) { if ((pc == '/') && (c == '*')) comment = 1; else if ((pc == '*') && (c == '/') && (comment)) comment = 0; } if (!comment) { if ((!quote) && (c == '"')) { quote = 1; i = 0; } else if ((quote) && (c == '"')) { line[i] = 0; quote = 0; if (context == 0) { /* Header */ sscanf(line, "%i %i %i %i", w, h, &ncolors, &cpp); if (ncolors > 32766) { fprintf(stderr, "IMLIB ERROR: XPM files wth colors > 32766 not supported\n"); free(line); return NULL; } if (cpp > 5) { fprintf(stderr, "IMLIB ERROR: XPM files with characters per pixel > 5 not supported\n"); free(line); return NULL; } if (*w > 32767) { fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n"); free(line); return NULL; } if (*h > 32767) { fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n"); free(line); return NULL; } cmap = malloc(sizeof(struct _cmap) * ncolors); if (!cmap) { free(line); return NULL; } /* SAFE -- Check for w,h in earlier code */ data = malloc(*w ** h * 3); if (!data) { free(cmap); free(line); return NULL; } ptr = data; end = ptr + (*w ** h * 3); j = 0; context++; } else if (context == 1) { /* Color Table */ if (j < ncolors) { int slen; int hascolor, iscolor; iscolor = 0; hascolor = 0; tok[0] = 0; col[0] = 0; s[0] = 0; len = strlen(line); strncpy(cmap[j].str, line, cpp); cmap[j].str[cpp] = 0; cmap[j].r = -1; cmap[j].transp = 0; for (k = cpp; k < len; k++) { if (line[k] != ' ') { s[0] = 0; sscanf(&line[k], "%256s", s); slen = strlen(s); k += slen; if (!strcmp(s, "c")) iscolor = 1; if ((!strcmp(s, "m")) || (!strcmp(s, "s")) || (!strcmp(s, "g4")) || (!strcmp(s, "g")) || (!strcmp(s, "c")) || (k >= len)) { if (k >= len) { if (col[0]) strcat(col, " "); if (strlen(col) + strlen(s) < sizeof(col)) strcat(col, s); } if (col[0]) { if (!strcasecmp(col, "none")) { transp = 1; cmap[j].transp = 1; } else { if ((((cmap[j].r < 0) || (!strcmp(tok, "c"))) && (!hascolor))) { XParseColor(id->x.disp, id->x.root_cmap, col, &xcol); cmap[j].r = xcol.red >> 8; cmap[j].g = xcol.green >> 8; cmap[j].b = xcol.blue >> 8; if ((cmap[j].r == 255) && (cmap[j].g == 0) && (cmap[j].b == 255)) cmap[j].r = 254; if (iscolor) hascolor = 1; } } } strcpy(tok, s); col[0] = 0; } else { if (col[0]) strcat(col, " "); strcat(col, s); } } } } j++; if (j >= ncolors) { if (cpp == 1) for (i = 0; i < ncolors; i++) lookup[(int)cmap[i].str[0] - 32][0] = i; if (cpp == 2) for (i = 0; i < ncolors; i++) lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i; context++; } } else { /* Image Data */ i = 0; if (cpp == 0) { /* Chars per pixel = 0? well u never know */ } if (cpp == 1) { if (transp) { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { col[0] = line[i]; if (cmap[lookup[(int)col[0] - 32][0]].transp) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; } else { *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b; } } } else { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { col[0] = line[i]; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b; } } } else if (cpp == 2) { if (transp) { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { col[0] = line[i++]; col[1] = line[i]; if (cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].transp) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; } else { *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b; } } } else { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { col[0] = line[i++]; col[1] = line[i]; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g; *ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b; } } } else { if (transp) { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { for (j = 0; j < cpp; j++, i++) { col[j] = line[i]; } col[j] = 0; i--; for (j = 0; j < ncolors; j++) { if (!strcmp(col, cmap[j].str)) { if (cmap[j].transp) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; } else { *ptr++ = (unsigned char)cmap[j].r; *ptr++ = (unsigned char)cmap[j].g; *ptr++ = (unsigned char)cmap[j].b; } j = ncolors; } } } } else { for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++) { for (j = 0; j < cpp; j++, i++) { col[j] = line[i]; } col[j] = 0; i--; for (j = 0; j < ncolors; j++) { if (!strcmp(col, cmap[j].str)) { *ptr++ = (unsigned char)cmap[j].r; *ptr++ = (unsigned char)cmap[j].g; *ptr++ = (unsigned char)cmap[j].b; j = ncolors; } } } } } } } } /* Scan in line from XPM file */ if ((!comment) && (quote) && (c != '"')) { if (c < 32) c = 32; else if (c > 127) c = 127; line[i++] = c; } if (i >= lsz) { lsz += 256; line = realloc(line, lsz); if(line == NULL) { free(cmap); return NULL; } } if ((ptr) && ((ptr - data) >= *w ** h * 3)) done = 1; } if (transp) *t = 1; else *t = 0; free(cmap); free(line); return data; } unsigned char * _LoadPPM(ImlibData * id, FILE * f, int *w, int *h) { int done; unsigned char *ptr; unsigned char chr; char s[256]; int a, b, i, j; int color, scale, ascii, bw; a = b = scale = ascii = bw = color = 0; fgets(s, 256, f); s[2] = 0; if (!strcmp(s, "P6")) color = 1; else if (!strcmp(s, "P5")) color = 0; else if (!strcmp(s, "P4")) bw = 1; else if (!strcmp(s, "P3")) { color = 1; ascii = 1; } else if (!strcmp(s, "P2")) { ascii = 1; } else if (!strcmp(s, "P1")) { ascii = 1; bw = 1; } else return NULL; done = 1; ptr = NULL; while (done) { if (fgets(s, 256, f) == NULL) break; if (s[0] != '#') { done = 0; sscanf(s, "%i %i", w, h); a = *w; b = *h; if (a > 32767) { fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n"); return NULL; } if (b > 32767) { fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n"); return NULL; } if (!bw) { fgets(s, 256, f); sscanf(s, "%i", &scale); } else scale = 99999; ptr = (unsigned char *)_imlib_malloc_image(a, b); if (!ptr) { fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file"); return ptr; } if ((color) && (!ascii) && (!bw)) { fread(ptr, a * b * 3, 1, f); } else if ((!color) && (!ascii) && (!bw)) { b = (a * b * 3); a = 0; while ((fread(&chr, 1, 1, f)) && (a < b)) { ptr[a++] = chr; ptr[a++] = chr; ptr[a++] = chr; } } else if ((!color) && (!ascii) && (bw)) { b = (a * b * 3); a = 0; j = 0; while ((fread(&chr, 1, 1, f)) && (a < b)) { for (i = 7; i >= 0; i--) { j++; if (j <= *w) { if (chr & (1 << i)) { ptr[a++] = 0; ptr[a++] = 0; ptr[a++] = 0; } else { ptr[a++] = 255; ptr[a++] = 255; ptr[a++] = 255; } } } if (j >= *w) j = 0; } } else if ((color) && (ascii) && (!bw)) { b = (a * b * 3); a = 0; i = 0; if (scale != 255) { while ((fread(&chr, 1, 1, f)) && (a < b)) { s[i++] = chr; if (!isdigit(chr)) { s[i - 1] = 0; if ((i > 1) && (isdigit(s[i - 2]))) { ptr[a++] = ((atoi(s)) * 255) / scale; } i = 0; } } } else { while ((fread(&chr, 1, 1, f)) && (a < b)) { s[i++] = chr; if (!isdigit(chr)) { s[i - 1] = 0; if ((i > 1) && (isdigit(s[i - 2]))) { ptr[a++] = atoi(s); } i = 0; } } } } else if ((!color) && (ascii) && (!bw)) { b = (a * b * 3); a = 0; i = 0; if (scale != 255) { while ((fread(&chr, 1, 1, f)) && (a < b)) { s[i++] = chr; if (!isdigit(chr)) { s[i - 1] = 0; if ((i > 1) && (isdigit(s[i - 2]))) { ptr[a++] = ((atoi(s)) * 255) / scale; ptr[a++] = ptr[a - 1]; ptr[a++] = ptr[a - 1]; } i = 0; } } } else { while ((fread(&chr, 1, 1, f)) && (a < b)) { s[i++] = chr; if (!isdigit(chr)) { s[i - 1] = 0; if ((i > 1) && (isdigit(s[i - 2]))) { ptr[a++] = atoi(s); ptr[a++] = ptr[a - 1]; ptr[a++] = ptr[a - 1]; } i = 0; } } } } else if ((!color) && (ascii) && (bw)) { } } } if (!ptr) return NULL; if (scale == 0) { free(ptr); return NULL; } if ((scale < 255) && (!ascii)) { int rot; unsigned char *po; if (scale <= 1) rot = 7; else if (scale <= 3) rot = 6; else if (scale <= 7) rot = 5; else if (scale <= 15) rot = 4; else if (scale <= 31) rot = 3; else if (scale <= 63) rot = 2; else rot = 1; if (rot > 0) { po = ptr; while (po < (ptr + (*w ** h * 3))) { *po++ <<= rot; *po++ <<= rot; *po++ <<= rot; } } } return ptr; } int ispnm(FILE *f) { char buf[8]; if (!f) return 0; fgets(buf, 8, f); rewind(f); if (!strcmp("P6", buf)) return 1; if (!strcmp("P5", buf)) return 1; if (!strcmp("P4", buf)) return 1; if (!strcmp("P3", buf)) return 1; if (!strcmp("P2", buf)) return 1; if (!strcmp("P1", buf)) return 1; return 0; } int isjpeg(FILE *f) { unsigned char buf[8]; if (!f) return 0; fread(buf, 1, 2, f); rewind(f); if ((buf[0] == 0xff) && (buf[1] == 0xd8)) return 1; return 0; } int ispng(FILE *f) { #ifdef HAVE_LIBPNG unsigned char buf[8]; if (!f) return 0; fread(buf, 1, 8, f); rewind(f); return (int)png_check_sig(buf, 8); #else return 0; #endif } int istiff(FILE *f) { char buf[8]; if (!f) return 0; fgets(buf, 5, f); rewind(f); if ((buf[0] == 'M') && (buf[1] == 'M') && (buf[2] == 0x00) && (buf[3] == 0x2a)) return 1; if ((buf[0] == 'I') && (buf[1] == 'I') && (buf[2] == 0x2a) && (buf[3] == 0x00)) return 1; return 0; } int iseim(FILE *f) { char buf[8]; if (!f) return 0; fread(buf, 1, 4, f); rewind(f); buf[4] = 0; if (!strncmp("EIM ", buf, 4)) return 1; return 0; } int isgif(FILE *f) { char buf[8]; if (!f) return 0; fread(buf, 1, 4, f); rewind(f); buf[4] = 0; if (!strcmp("GIF8", buf)) return 1; return 0; } int isxpm(FILE *f) { char buf[11]; if (!f) return 0; fread(buf, 1, 9, f); rewind(f); buf[9] = 0; if (!strcmp("/* XPM */", buf)) return 1; return 0; } int isbmp(FILE *f) { char buf[3]; if (!f) return 0; fread(buf, 1, 2, f); rewind(f); buf[2] = 0; if (!strcmp("BM", buf)) return 1; return 0; } ImlibImage * Imlib_load_image(ImlibData * id, char *file) { int w, h; unsigned char *data; ImlibImage *im; char s[4096]; char fil[4096]; char *iden; char *e; char cmd[4096]; FILE *p; int eim; int fmt; int trans; eim = 0; fmt = 0; data = NULL; if (!file) return NULL; if (id->cache.on_image) if ((im = find_image(id, file))) { if (im->rgb_width == 0 || im->rgb_height == 0) { Imlib_destroy_image(id, im); return NULL; } else return im; } if (!strcmp(file,"-")) { p = stdin; } else { p = fopen(file, "rb"); } if (!p) return NULL; strncpy(fil, file, sizeof(fil)); iden = _SplitID(fil); e = _GetExtension(fil); if (ispnm(p)) { fmt = 0; } else if (isjpeg(p)) { fmt = 2; } else if (istiff(p)) { fmt = 3; } else if (iseim(p)) { eim = 1; fmt = 9999; } else if (isxpm(p)) { fmt = 5; } else if (ispng(p)) { fmt = 1; } else if (isgif(p)) { fmt = 4; } else if (isbmp(p)) { fmt = 6; } trans = 0; if ((!eim) && (!data)) { switch (fmt) { case 6: data = _LoadBMP(id, p, &w, &h, &trans); break; case 5: data = _LoadXPM(id, p, &w, &h, &trans); break; #ifdef HAVE_LIBGIF case 4: data = _LoadGIF(id, p, &w, &h, &trans); break; #endif #ifdef HAVE_LIBTIFF case 3: data = _LoadTIFF(id, p, file, &w, &h, &trans); break; #endif #ifdef HAVE_LIBJPEG case 2: data = _LoadJPEG(id, p, &w, &h); break; #endif #ifdef HAVE_LIBPNG case 1: data = _LoadPNG(id, p, &w, &h, &trans); break; #endif default: data = _LoadPPM(id, p, &w, &h); break; } } if (p != stdin) fclose(p); if ((!eim) && (!data)) { fprintf(stderr, "IMLIB ERROR: Cannot load image: %s\n" "All fallbacks failed.\n", fil); return NULL; } if (!w || !h) { fprintf(stderr, "IMLIB ERROR: zero image\n" ); if(data) free(data); return NULL; } im = (ImlibImage *) malloc(sizeof(ImlibImage)); if (!im) { fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for image structure\n"); if (data) free(data); return NULL; } im->alpha_data = NULL; if (trans) { im->shape_color.r = 255; im->shape_color.g = 0; im->shape_color.b = 255; } else { im->shape_color.r = -1; im->shape_color.g = -1; im->shape_color.b = -1; } im->border.left = 0; im->border.right = 0; im->border.top = 0; im->border.bottom = 0; im->cache = 1; im->rgb_data = data; im->rgb_width = w; im->rgb_height = h; im->pixmap = 0; im->shape_mask = 0; if (eim) { char s1[256], s2[256]; int num, size; int r, g, b; int br, bl, bt, bb; /* Load Native-as-can-be EIM format (Enlightenment IMlib format) */ if (!strcmp(file,"-")) p = stdin; else { #ifndef __EMX__ p = fopen(file, "r"); #else p = fopen(file, "rt"); #endif } if (!p) { free(im); return NULL; } fgets(s, 4096, p); if ((s[0] != 'E') && (s[1] != 'I') && (s[2] != 'M') && (s[3] != ' ')) { fclose(p); free(im); return NULL; } sscanf(s, "%256s %i", s1, &num); if (num <= 0) { fclose(p); free(im); return NULL; } while (fgets(s, 4096, p)) { sscanf(s, "%256s", s1); if (!strcmp("IMAGE", s1)) { sscanf(s, "%256s %i %256s %i %i %i %i %i %i %i %i %i", s1, &size, s2, &w, &h, &r, &g, &b, &bl, &br, &bt, &bb); if (!iden[0]) break; else if (!strcmp(iden, s2)) break; if (size > 0) fseek(p, size, SEEK_CUR); } } im->rgb_data = _imlib_malloc_image(w, h); if (!im->rgb_data) { fclose(p); free(im); return NULL; } im->shape_color.r = r; im->shape_color.g = g; im->shape_color.b = b; im->rgb_width = w; im->rgb_height = h; im->border.left = bl; im->border.right = br; im->border.top = bt; im->border.bottom = bb; fread(im->rgb_data, 1, w * h * 3, p); fclose(p); if (iden[0]) { #ifndef __EMX__ strncat(fil, ":", sizeof(fil) - strlen(fil)); #else strncat(fil, ";", sizeof(fil) - strlen(fil)); #endif strncat(fil, iden, sizeof(fil) - strlen(fil)); } } im->mod.gamma = id->mod.gamma; im->mod.brightness = id->mod.brightness; im->mod.contrast = id->mod.contrast; im->rmod.gamma = id->rmod.gamma; im->rmod.brightness = id->rmod.brightness; im->rmod.contrast = id->rmod.contrast; im->gmod.gamma = id->gmod.gamma; im->gmod.brightness = id->gmod.brightness; im->gmod.contrast = id->gmod.contrast; im->bmod.gamma = id->bmod.gamma; im->bmod.brightness = id->bmod.brightness; im->bmod.contrast = id->bmod.contrast; im->filename = malloc(strlen(file) + 1); if (im->filename) strcpy(im->filename, file); if ((id->cache.on_image) && (im)) add_image(id, im, fil); calc_map_tables(id, im); return im; } int Imlib_save_image_to_eim(ImlibData * id, ImlibImage * im, char *file) { char fil[4096]; char *iden; FILE *f; int size; if ((!id) || (!im) || (!file)) return 0; strncpy(fil, file, sizeof(fil)); iden = _SplitID(fil); if (!iden[0]) iden = "default"; f = fopen(fil, "w"); if (!f) return 0; size = im->rgb_width * im->rgb_height * 3; fprintf(f, "EIM 1\n"); fprintf(f, "IMAGE %i %s %i %i %i %i %i %i %i %i %i\n", size, iden, im->rgb_width, im->rgb_height, im->shape_color.r, im->shape_color.g, im->shape_color.b, im->border.left, im->border.right, im->border.top, im->border.bottom); if (fwrite(im->rgb_data, size, 1, f) != 1) { fclose(f); return 0; } fclose(f); return 1; } int Imlib_add_image_to_eim(ImlibData * id, ImlibImage * im, char *file) { char fil[4096]; char *iden; FILE *f; int size; if ((!id) || (!im) || (!file)) return 0; strncpy(fil, file, sizeof(fil)); iden = _SplitID(file); if (!iden[0]) strcpy(iden, "default"); f = fopen(fil, "a"); if (!f) return 0; size = im->rgb_width * im->rgb_height * 3; fprintf(f, "IMAGE %i %s %i %i %i %i %i %i %i %i %i\n", size, iden, im->rgb_width, im->rgb_height, im->shape_color.r, im->shape_color.g, im->shape_color.b, im->border.left, im->border.right, im->border.top, im->border.bottom); if (fwrite(im->rgb_data, size, 1, f) != 1) { fclose(f); return 0; } fclose(f); return 1; } int Imlib_save_image_to_ppm(ImlibData * id, ImlibImage * im, char *file) { FILE *f; if ((!id) || (!im) || (!file)) return 0; #ifndef __EMX__ f = fopen(file, "w"); #else f = fopen(file, "wb"); #endif if (!f) return 0; fprintf(f, "P6\n"); fprintf(f, "%i %i\n255\n", im->rgb_width, im->rgb_height); if (fwrite(im->rgb_data, im->rgb_width * im->rgb_height * 3, 1, f) != 1) { fclose(f); return 0; } fclose(f); return 1; }