static int load_image(Image *p, Stream *st) { unsigned char *buf, *d; unsigned int size; int w, h; /* Read whole stream into buffer... */ size = 0; buf = NULL; { unsigned char *tmp; int len; int bufsize = 65536; for (;;) { if ((tmp = realloc(buf, bufsize)) == NULL) { free(buf); return LOAD_ERROR; } buf = tmp; len = stream_read(st, buf + size, bufsize - size); size += len; if (len < bufsize - size) break; bufsize += 65536; } } d = WebPDecodeRGB(buf, size, &w, &h); if (d == NULL) return 0; image_width(p) = w; image_height(p) = h; p->type = _RGB24; p->bits_per_pixel = 24; p->depth = 24; debug_message_fnc("WEBP (%d,%d) %d bytes\n", image_width(p), image_height(p), size); image_bpl(p) = (image_width(p) * p->bits_per_pixel) >> 3; memory_set(image_image(p), d, _NORMAL, image_bpl(p) * image_height(p), image_bpl(p) * image_height(p)); return 1; }
DEFINE_LOADER_PLUGIN_LOAD(p, st, vw #if !defined(IDENTIFY_BEFORE_LOAD) __attribute__((unused)) #endif , c #if !defined(IDENTIFY_BEFORE_LOAD) __attribute__((unused)) #endif , priv #if !defined(IDENTIFY_BEFORE_LOAD) __attribute__((unused)) #endif ) { jas_image_t *ji; jas_stream_t *js; unsigned char *d; char *buf = NULL; int k, cmp[3]; unsigned int i, j; int tlx, tly; int vs, hs; //debug_message("JasPer: load() called\n"); #ifdef IDENTIFY_BEFORE_LOAD { LoaderStatus status; if ((status = identify(p, st, vw, c, priv)) != LOAD_OK) return status; stream_rewind(st); } #endif /* Read whole stream into buffer... */ { char *tmp; int size = 0, len; int bufsize = 65536; for (;;) { if ((tmp = realloc(buf, bufsize)) == NULL) { free(buf); return LOAD_ERROR; } buf = tmp; len = stream_read(st, (unsigned char *)(buf + size), bufsize - size); size += len; if (len < bufsize - size) break; bufsize += 65536; } if ((js = jas_stream_memopen(buf, size)) == NULL) { free(buf); return LOAD_ERROR; } } /* loading... */ if ((ji = jas_image_decode(js, -1, 0)) == NULL) { err_message_fnc("jas_image_decode() failed.\n"); goto error_clear; } /* colorspace conversion */ { jas_cmprof_t *jc; jas_image_t *new_ji; if ((jc = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)) == NULL) goto error_destroy_free; if ((new_ji = jas_image_chclrspc(ji, jc, JAS_CMXFORM_INTENT_PER)) == NULL) goto error_destroy_free; jas_image_destroy(ji); ji = new_ji; } jas_stream_close(js); free(buf); debug_message("JasPer: jas_image_decode() OK: (%ld,%ld)\n", jas_image_cmptwidth(ji, 0), jas_image_cmptheight(ji, 0)); /* convert to enfle format */ p->bits_per_pixel = 24; p->type = _RGB24; p->depth = 24; cmp[0] = jas_image_getcmptbytype(ji, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); cmp[1] = jas_image_getcmptbytype(ji, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); cmp[2] = jas_image_getcmptbytype(ji, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); /* dimension */ image_width(p) = jas_image_cmptwidth(ji, cmp[0]); image_height(p) = jas_image_cmptheight(ji, cmp[0]); image_left(p) = 0; image_top(p) = 0; image_bpl(p) = image_width(p) * 3; tlx = jas_image_cmpttlx(ji, cmp[0]); tly = jas_image_cmpttly(ji, cmp[0]); vs = jas_image_cmptvstep(ji, cmp[0]); hs = jas_image_cmpthstep(ji, cmp[0]); debug_message("JasPer: tlx %d tly %d vs %d hs %d ncomponents %d\n", tlx, tly, vs, hs, jas_image_numcmpts(ji)); /* memory allocation */ if ((d = memory_alloc(image_image(p), image_bpl(p) * image_height(p))) == NULL) { err_message("No enough memory (%d bytes)\n", image_bpl(p) * image_height(p)); goto error_destroy_free; } for (i = 0; i < image_height(p); i++) { for (j = 0; j < image_width(p); j++) { for (k = 0; k < 3; k++) *d++ = jas_image_readcmptsample(ji, cmp[k], j, i); } } jas_image_destroy(ji); return LOAD_OK; error_destroy_free: jas_image_destroy(ji); error_clear: return LOAD_ERROR; }
DEFINE_SAVER_PLUGIN_SAVE(p, fp, c, params) { struct jpeg_compress_struct *cinfo = malloc(sizeof(struct jpeg_compress_struct)); struct my_error_mgr jerr; JSAMPROW buffer[1]; /* output row buffer */ int quality, result; debug_message("jpeg: save (%s) (%d, %d) called.\n", image_type_to_string(p->type), image_width(p), image_height(p)); if (cinfo == NULL) return 0; switch (p->type) { case _BITMAP_LSBFirst: case _BITMAP_MSBFirst: case _GRAY_ALPHA: case _INDEX: case _RGB565: case _BGR565: case _RGB555: case _BGR555: case _BGR24: case _RGBA32: case _ABGR32: case _ARGB32: case _BGRA32: show_message("Saving of %s type image is not yet implemented.\n", image_type_to_string(p->type)); return 0; case _GRAY: case _RGB24: break; default: fprintf(stderr, "Unknown image type: %d (maybe bug)\n", p->type); return 0; } cinfo->err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(cinfo); free(cinfo); return 0; } quality = config_get_int(c, "/enfle/plugins/saver/jpeg/quality", &result); if (!result) quality = JPEG_SAVE_DEFAULT_QUALITY; else if (quality < 1 || quality > 100) { show_message("Invalid quality %d: defaults to %d.\n", quality, JPEG_SAVE_DEFAULT_QUALITY); quality = JPEG_SAVE_DEFAULT_QUALITY; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_compress(cinfo); jpeg_stdio_dest(cinfo, fp); cinfo->image_width = image_width(p); cinfo->image_height = image_height(p); if (p->type == _GRAY) { cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; } else { cinfo->input_components = 3; cinfo->in_color_space = JCS_RGB; } jpeg_set_defaults(cinfo); jpeg_set_quality(cinfo, quality, TRUE); jpeg_start_compress(cinfo, TRUE); while (cinfo->next_scanline < cinfo->image_height) { buffer[0] = (JSAMPROW)(memory_ptr(image_image(p)) + image_bpl(p) * cinfo->next_scanline); (void)jpeg_write_scanlines(cinfo, buffer, 1); } (void)jpeg_finish_compress(cinfo); jpeg_destroy_compress(cinfo); free(cinfo); debug_message("jpeg: saved.\n"); return 1; }
static int load_image(Image *p, Stream *st) { unsigned char buf[BUFSIZE], *pp, *d; unsigned int file_size, header_size, image_size, offset_to_image; unsigned short int biPlanes; unsigned int bytes_per_pal; int i, c, c2, y, compress_method; if (stream_read(st, buf, 12) != 12) return 0; file_size = utils_get_little_uint32(&buf[0]); offset_to_image = utils_get_little_uint32(&buf[8]); if (file_size < offset_to_image) return 0; if (!stream_read_little_uint32(st, &header_size)) return 0; if (header_size > 64) return 0; if (stream_read(st, buf, header_size - 4) != (int)(header_size - 4)) return 0; if (header_size >= WIN_BMP_HEADER_SIZE) { image_width(p) = utils_get_little_uint32(&buf[0]); image_height(p) = utils_get_little_uint32(&buf[4]); biPlanes = utils_get_little_uint16(&buf[8]); p->bits_per_pixel = utils_get_little_uint16(&buf[10]); } else { image_width(p) = utils_get_little_uint16(&buf[0]); image_height(p) = utils_get_little_uint16(&buf[2]); biPlanes = utils_get_little_uint16(&buf[4]); p->bits_per_pixel = utils_get_little_uint16(&buf[6]); } if (biPlanes != 1) return 0; if (image_width(p) > 10000 || image_height(p) > 10000) return 0; switch (p->bits_per_pixel) { case 1: p->type = _BITMAP_MSBFirst; /* XXX: check order */ p->depth = p->bits_per_pixel; break; case 4: p->type = _INDEX44; p->depth = 4; break; case 8: p->type = _INDEX; p->depth = 8; break; case 16: p->type = _RGB555; p->depth = 16; break; case 24: p->type = _BGR24; p->depth = 24; break; case 32: p->type = _BGRA32; p->depth = 24; break; default: show_message("bmp: read_header: unknown bpp %d detected.\n", p->bits_per_pixel); return 0; } compress_method = 0; if (header_size >= WIN_BMP_HEADER_SIZE) { compress_method = utils_get_little_uint16(&buf[12]); image_size = utils_get_little_uint32(&buf[16]); image_size = image_size; // dummy } /* other header informations are intentionally ignored */ if (p->depth <= 8) { p->ncolors = 1 << p->depth; bytes_per_pal = (header_size >= WIN_BMP_HEADER_SIZE) ? 4 : 3; if (p->ncolors * bytes_per_pal > BUFSIZE) { err_message_fnc("BUFSIZE is too small. It must be greater than %d.\n", p->ncolors * bytes_per_pal); return 0; } if (stream_read(st, buf, p->ncolors * bytes_per_pal) != (int)(p->ncolors * bytes_per_pal)) return 0; for (i = 0; i < (int)p->ncolors; i++) { p->colormap[i][0] = buf[bytes_per_pal * i + 2]; p->colormap[i][1] = buf[bytes_per_pal * i + 1]; p->colormap[i][2] = buf[bytes_per_pal * i + 0]; } } else if (p->depth == 16 && compress_method == 3) { /* Read bitmasks */ if (stream_read(st, buf, 3 * 4) != 3 * 4) return 0; unsigned int rm = utils_get_little_uint32(buf); unsigned int gm = utils_get_little_uint32(buf + 4); unsigned int bm = utils_get_little_uint32(buf + 8); if (rm == 0xf800) p->type = _RGB565; else if (rm == 0x7c00) p->type = _RGB555; else warning_fnc("Mask: R %X G %X B %X is not supported\n", rm, gm, bm); compress_method = 0; } image_bpl(p) = (image_width(p) * p->bits_per_pixel) >> 3; image_bpl(p) += (4 - (image_bpl(p) % 4)) % 4; debug_message_fnc("(%d, %d): bpp %d depth %d compress %d\n", image_width(p), image_height(p), p->bits_per_pixel, p->depth, compress_method); if ((d = memory_alloc(image_image(p), image_bpl(p) * image_height(p))) == NULL) return 0; stream_seek(st, offset_to_image, _SET); pp = d + image_bpl(p) * (image_height(p) - 1); switch (compress_method) { case BI_RGB: for (i = (int)(image_height(p) - 1); i >= 0; i--) { stream_read(st, pp, image_bpl(p)); pp -= image_bpl(p); } break; case BI_RLE4: if (p->depth != 4) show_message("Compressed RI_BLE4 bitmap with depth %d != 4.\n", p->depth); /* RLE compressed data */ /* Not complete. */ y = image_height(p); while ((c = stream_getc(st)) != -1 && y >= 0) { if (c != 0) { /* code mode */ c2 = stream_getc(st); show_message_fnc("len %d data %d\n", c, c2); for (i = 0; i < c; i += 2) { *pp++ = (unsigned char)c2; } } else { if ((c = stream_getc(st)) == 0) { /* line end */ show_message_fnc("line end %d\n", y); pp = d + image_bpl(p) * (y - 1); y--; } else if (c == 1) { /* image end */ break; } else if (c == 2) { /* offset */ c = stream_getc(st); c2 = stream_getc(st); show_message_fnc("offset %d, %d\n", c, c2); pp += (c - c2 * image_width(p)) / 2; } else { /* absolute mode */ show_message_fnc("abs len %d\n", c); for (i = 0; i < c; i += 2) *pp++ = (unsigned char)stream_getc(st); if (c % 2 != 0) /* read dummy */ c = stream_getc(st); } } } break; case BI_RLE8: if (p->depth != 8) show_message("Compressed RI_BLE8 bitmap with depth %d != 8.\n", p->depth); /* RLE compressed data */ y = image_height(p); while ((c = stream_getc(st)) != -1 && y >= 0) { if (c != 0) { /* code mode */ c2 = stream_getc(st); for (i = 0; i < c; i++) { *pp++ = (unsigned char)c2; } } else { if ((c = stream_getc(st)) == 0) { /* line end */ pp = d + image_bpl(p) * (y - 1); y--; } else if (c == 1) { /* image end */ break; } else if (c == 2) { /* offset */ c = stream_getc(st); c2 = stream_getc(st); pp += (c - c2 * image_width(p)); } else { /* absolute mode */ for (i = 0; i < c; i++) *pp++ = (unsigned char)stream_getc(st); if (c % 2 != 0) /* read dummy */ c = stream_getc(st); } } } break; default: show_message("Compressed bitmap (method = %d) not supported.\n", compress_method); return 0; } return 1; }
/* converts giflib format image into enfle format image */ static int gif_convert(Image *p, GIF_info *g_info, GIF_image *image) { GIF_ct *ct; int i, if_animated; //int transparent_disposal; #if 0 if (image->next != NULL) { if ((p->next = image_create()) == NULL) { image_destroy(p); return 0; } if (!gif_convert(p->next, g_info, image->next)) { image_destroy(p); return 0; } } else p->next = NULL; #endif //swidth = g_info->sd->width; //sheight = g_info->sd->height; image_left(p) = image->id->left; image_top(p) = image->id->top; image_width(p) = image->id->width; image_height(p) = image->id->height; #if 0 if (image_width(p) > swidth || image_height(p) > sheight) { show_message("screen (%dx%d) but image (%dx%d)\n", swidth, sheight, p->width, p->height); swidth = image_width(p); sheight = image_height(p); } #endif p->ncolors = image->id->lct_follows ? 1 << image->id->depth : 1 << g_info->sd->depth; p->type = _INDEX; //p->delay = image->gc->delay ? image->gc->delay : 1; if_animated = g_info->npics > 1 ? 1 : 0; debug_message("GIF: %d pics animation %d\n", g_info->npics, if_animated); #if 0 if (image->gc->transparent) { p->transparent_disposal = if_animated ? _TRANSPARENT : transparent_disposal; p->transparent.index = image->gc->transparent_index; } else p->transparent_disposal = _DONOTHING; p->image_disposal = image->gc->disposal; p->background.index = g_info->sd->back; #endif if (image->id->lct_follows) ct = image->id->lct; else if (g_info->sd->gct_follows) ct = g_info->sd->gct; else { fprintf(stderr, "Null color table..\n"); ct = NULL; } for (i = 0; i < (int)p->ncolors; i++) { p->colormap[i][0] = ct->cell[i]->value[0]; p->colormap[i][1] = ct->cell[i]->value[1]; p->colormap[i][2] = ct->cell[i]->value[2]; } image_bpl(p) = image_width(p); if (!image_image(p)) image_image(p) = memory_create(); if (memory_alloc(image_image(p), image_bpl(p) * image_height(p)) == NULL) return 0; memcpy(memory_ptr(image_image(p)), image->data, image_bpl(p) * image_height(p)); return 1; }