From: Pavel Charvat Date: Tue, 25 Jul 2006 19:32:21 +0000 (+0200) Subject: little changes in image I/O interface X-Git-Tag: holmes-import~632 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=e4dd255c7797e331c82a7eedc0d6c751dcf82461;p=libucw.git little changes in image I/O interface added some image parameters needed for gather/format/image.c --- diff --git a/images/image-tool.c b/images/image-tool.c index 94fdd44d..d9b20adc 100644 --- a/images/image-tool.c +++ b/images/image-tool.c @@ -24,13 +24,14 @@ Usage: image-tool [options] infile [outfile]\n\ -f --input-format input image format (jpeg, gif, png)\n\ -F --output-format output image format\n\ -s --size force output dimensions (100x200)\n\ --b --fit-box scale to fit the box (100x200)\n\ --c --colorspace force output colorspace (gray, grayalpha, rgb, rgbalpha)\n\ +-b --fit-to-box scale to fit the box (100x200)\n\ +-c --colorspace force output colorspace (Gray, GrayAlpha, RGB, RGBAlpha)\n\ +-Q --jpeg-quality JPEG quality (1..100)\n\ ", stderr); exit(1); } -static char *shortopts = "qf:F:s:b:c:" CF_SHORT_OPTS; +static char *shortopts = "qf:F:s:b:c:Q:" CF_SHORT_OPTS; static struct option longopts[] = { CF_LONG_OPTS @@ -38,8 +39,9 @@ static struct option longopts[] = { "input-format", 0, 0, 'f' }, { "output-format", 0, 0, 'F' }, { "size", 0, 0, 's' }, - { "fit-box", 0, 0, 'b' }, + { "fit-to-box", 0, 0, 'b' }, { "colorspace", 0, 0, 'c' }, + { "jpeg-quality", 0, 0, 'Q' }, { NULL, 0, 0, 0 } }; @@ -50,8 +52,9 @@ static byte *output_file_name; static enum image_format output_format; static uns cols; static uns rows; -static uns fit_box; +static uns fit_to_box; static uns channels_format; +static uns jpeg_quality; #define MSG(x...) do{ if (verbose) log(L_INFO, ##x); }while(0) @@ -82,7 +85,7 @@ main(int argc, char **argv) *r++ = 0; if (!(cols = atoi(optarg)) || !(rows = atoi(r))) usage(); - fit_box = 0; + fit_to_box = 0; break; } case 'b': @@ -93,13 +96,17 @@ main(int argc, char **argv) *r++ = 0; if (!(cols = atoi(optarg)) || !(rows = atoi(r))) usage(); - fit_box = 1; + fit_to_box = 1; break; } case 'c': if (!(channels_format = image_name_to_channels_format(optarg))) usage(); break; + case 'Q': + if (!(jpeg_quality = atoi(optarg))) + usage(); + break; default: usage(); } @@ -126,14 +133,15 @@ main(int argc, char **argv) bclose(io.fastbuf); printf("Format: %s\n", image_format_to_extension(io.format) ? : (byte *)"?"); printf("Dimensions: %dx%d\n", io.cols, io.rows); - printf("Colorspace: %s\n", image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); + printf("Colorspace: %s\n", io.has_palette ? (byte *)"Palette" : image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); + printf("NumColors: %d\n", io.number_of_colors); } else { MSG("%s %dx%d %s", image_format_to_extension(io.format) ? : (byte *)"?", io.cols, io.rows, - image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); + io.has_palette ? (byte *)"Palette" : image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); if (cols) - if (fit_box) + if (fit_to_box) { image_dimensions_fit_to_box(&io.cols, &io.rows, MIN(cols, 0xffff), MIN(rows, 0xffff), 0); } @@ -144,6 +152,8 @@ main(int argc, char **argv) } if (channels_format) io.flags = io.flags & ~IMAGE_PIXEL_FORMAT | channels_format; + if (jpeg_quality) + io.jpeg_quality = jpeg_quality; TRY(image_io_read_data(&io, 0)); bclose(io.fastbuf); MSG("Writing %s", output_file_name); diff --git a/images/image.c b/images/image.c index 1db02b10..e04d839c 100644 --- a/images/image.c +++ b/images/image.c @@ -152,7 +152,7 @@ image_clone(struct image_thread *it, struct image *src, uns flags, struct mempoo } void -image_destroy(struct image_thread *it UNUSED, struct image *img) +image_destroy(struct image *img) { DBG("image_destroy(img=%p)", img); xfree((byte *)img); diff --git a/images/images.h b/images/images.h index 91c43d19..31c25dc8 100644 --- a/images/images.h +++ b/images/images.h @@ -43,6 +43,13 @@ image_thread_err(struct image_thread *thread, uns code, char *msg) thread->err_msg = (byte *)msg; } +static inline void +image_thread_err_dup(struct image_thread *thread, uns code, char *msg) +{ + thread->err_code = code; + thread->err_msg = mp_strdup(thread->pool, msg); +} + void image_thread_err_format(struct image_thread *thread, uns code, char *msg, ...); /* basic image manupulation */ @@ -80,7 +87,7 @@ struct image { struct image *image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool *pool); struct image *image_clone(struct image_thread *it, struct image *src, uns flags, struct mempool *pool); -void image_destroy(struct image_thread *it, struct image *img); /* only with NULL mempool */ +void image_destroy(struct image *img); /* only with NULL mempool */ void image_clear(struct image_thread *it, struct image *img); byte *color_space_to_name(enum color_space cs); @@ -103,27 +110,29 @@ enum image_format { }; struct image_io { - struct image *image; - struct fastbuf *fastbuf; - enum image_format format; - struct mempool *pool; - u32 cols; - u32 rows; - u32 flags; + /* R - read_header input */ + /* H - read_header output */ + /* I - read_data input */ + /* O - read_data output */ + /* W - write input */ + + struct image *image; /* [ OW] - image data */ + enum image_format format; /* [R W] - file format (IMAGE_FORMAT_x) */ + struct fastbuf *fastbuf; /* [R W] - source/destination stream */ + struct mempool *pool; /* [ I ] - parameter to image_new */ + u32 cols; /* [ HI ] - number of columns, parameter to image_new */ + u32 rows; /* [ HI ] - number of rows, parameter to image_new */ + u32 flags; /* [ HI ] - parameter to image new, read_header fills IMAGE_CHANNELS_FORMAT */ + u32 jpeg_quality; /* [ W] - JPEG compression quality (1..100) */ + u32 number_of_colors; /* [ H ] - number of image colors */ + u32 has_palette; /* [ H ] - true for image with indexed colors */ + /* internals */ struct image_thread *thread; struct mempool *internal_pool; int image_destroy; void *read_data; void (*read_cancel)(struct image_io *io); - union { - struct { - } jpeg; - struct { - } png; - struct { - } gif; - }; }; void image_io_init(struct image_thread *it, struct image_io *io); diff --git a/images/io-libjpeg.c b/images/io-libjpeg.c index 1b467970..dddfd79f 100644 --- a/images/io-libjpeg.c +++ b/images/io-libjpeg.c @@ -48,7 +48,7 @@ libjpeg_read_error_exit(j_common_ptr cinfo) struct libjpeg_err *e = (struct libjpeg_err *)cinfo->err; byte buf[JMSG_LENGTH_MAX]; e->pub.format_message(cinfo, buf); - image_thread_err(e->io->thread, IMAGE_ERR_READ_FAILED, buf); + image_thread_err_dup(e->io->thread, IMAGE_ERR_READ_FAILED, buf); longjmp(e->setjmp_buf, 1); } @@ -59,7 +59,7 @@ libjpeg_write_error_exit(j_common_ptr cinfo) struct libjpeg_err *e = (struct libjpeg_err *)cinfo->err; byte buf[JMSG_LENGTH_MAX]; e->pub.format_message(cinfo, buf); - image_thread_err(e->io->thread, IMAGE_ERR_WRITE_FAILED, buf); + image_thread_err_dup(e->io->thread, IMAGE_ERR_WRITE_FAILED, buf); longjmp(e->setjmp_buf, 1); } @@ -217,20 +217,19 @@ libjpeg_read_header(struct image_io *io) /* Read JPEG header and setup decompression options */ DBG("Reading image header"); jpeg_read_header(&i->cinfo, TRUE); - if (!(io->flags & IMAGE_COLOR_SPACE)) - switch (i->cinfo.jpeg_color_space) - { - case JCS_GRAYSCALE: - io->flags |= COLOR_SPACE_GRAYSCALE; - break; - default: - io->flags |= COLOR_SPACE_RGB; - break; - } - if (!io->cols) - io->cols = i->cinfo.image_width; - if (!io->rows) - io->rows = i->cinfo.image_height; + switch (i->cinfo.jpeg_color_space) + { + case JCS_GRAYSCALE: + io->flags = COLOR_SPACE_GRAYSCALE; + io->number_of_colors = 1 << 8; + break; + default: + io->flags = COLOR_SPACE_RGB; + io->number_of_colors = 1 << 24; + break; + } + io->cols = i->cinfo.image_width; + io->rows = i->cinfo.image_height; io->read_cancel = libjpeg_read_cancel; return 1; @@ -275,7 +274,7 @@ libjpeg_read_data(struct image_io *io) DBG("Libjpeg failed to read the image, longjump saved us"); jpeg_destroy_decompress(&i->cinfo); if (need_scale || !io->pool) - image_destroy(io->thread, img); + image_destroy(img); return 0; } @@ -335,17 +334,17 @@ libjpeg_read_data(struct image_io *io) struct image *dest = image_new(io->thread, io->cols, io->rows, io->flags, io->pool); if (!dest) { - image_destroy(io->thread, img); + image_destroy(img); return 0; } if (!(image_scale(io->thread, dest, img))) { - image_destroy(io->thread, img); + image_destroy(img); if (!io->pool) - image_destroy(io->thread, dest); + image_destroy(dest); return 0; } - image_destroy(io->thread, img); + image_destroy(img); io->image = dest; } else @@ -403,6 +402,8 @@ libjpeg_write(struct image_io *io) return 0; } jpeg_set_defaults(&i.cinfo); + if (io->jpeg_quality) + jpeg_set_quality(&i.cinfo, MIN(io->jpeg_quality, 100), 1); /* Compress the image */ jpeg_start_compress(&i.cinfo, TRUE); diff --git a/images/io-libmagick.c b/images/io-libmagick.c index b74c7174..aa426872 100644 --- a/images/io-libmagick.c +++ b/images/io-libmagick.c @@ -91,22 +91,20 @@ libmagick_read_header(struct image_io *io) } /* Fill image parameters */ - if (!io->cols) - io->cols = rd->image->columns; - if (!io->rows) - io->rows = rd->image->rows; - if (!(io->flags & IMAGE_CHANNELS_FORMAT)) + io->cols = rd->image->columns; + io->rows = rd->image->rows; + switch (rd->image->colorspace) { - switch (rd->image->colorspace) - { - case GRAYColorspace: - io->flags |= COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; - break; - default: - io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA; - break; - } + case GRAYColorspace: + io->flags |= COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; + break; + default: + io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA; + break; } + io->number_of_colors = rd->image->colors; + if (rd->image->storage_class == PseudoClass && rd->image->compression != JPEGCompression) + io->has_palette = 1; io->read_cancel = libmagick_read_cancel; return 1; @@ -223,7 +221,7 @@ libmagick_read_data(struct image_io *io) if (unlikely(!img2)) goto err2; int result = image_scale(io->thread, img2, img); - image_destroy(io->thread, img); + image_destroy(img); img = img2; need_destroy = !io->pool; if (unlikely(!result)) @@ -240,7 +238,7 @@ err: libmagick_destroy_read_data(rd); err2: if (need_destroy) - image_destroy(io->thread, img); + image_destroy(img); return 0; } @@ -274,6 +272,8 @@ libmagick_write(struct image_io *io) { case IMAGE_FORMAT_JPEG: strcpy(info->magick, "JPEG"); + if (io->jpeg_quality) + info->quality = MIN(io->jpeg_quality, 100); break; case IMAGE_FORMAT_PNG: strcpy(info->magick, "PNG"); diff --git a/images/io-libpng.c b/images/io-libpng.c index 4b4864f6..c2847a82 100644 --- a/images/io-libpng.c +++ b/images/io-libpng.c @@ -43,7 +43,7 @@ static void NONRET libpng_read_error(png_structp png_ptr, png_const_charp msg) { DBG("libpng_read_error()"); - image_thread_err(png_get_error_ptr(png_ptr), IMAGE_ERR_READ_FAILED, (byte *)msg); + image_thread_err_dup(png_get_error_ptr(png_ptr), IMAGE_ERR_READ_FAILED, (byte *)msg); longjmp(png_jmpbuf(png_ptr), 1); } @@ -51,7 +51,7 @@ static void NONRET libpng_write_error(png_structp png_ptr, png_const_charp msg) { DBG("libpng_write_error()"); - image_thread_err(png_get_error_ptr(png_ptr), IMAGE_ERR_WRITE_FAILED, (byte *)msg); + image_thread_err_dup(png_get_error_ptr(png_ptr), IMAGE_ERR_WRITE_FAILED, (byte *)msg); longjmp(png_jmpbuf(png_ptr), 1); } @@ -138,31 +138,40 @@ libpng_read_header(struct image_io *io) png_get_IHDR(rd->png_ptr, rd->info_ptr, &rd->cols, &rd->rows, &rd->bit_depth, &rd->color_type, NULL, NULL, NULL); /* Fill image_io values */ - if (!io->cols) - io->cols = rd->cols; - if (!io->rows) - io->rows = rd->rows; - if (!(io->flags & IMAGE_CHANNELS_FORMAT)) - switch (rd->color_type) - { - case PNG_COLOR_TYPE_GRAY: - io->flags |= COLOR_SPACE_GRAYSCALE; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - io->flags |= COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; - break; - case PNG_COLOR_TYPE_RGB: - io->flags |= COLOR_SPACE_RGB; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - case PNG_COLOR_TYPE_PALETTE: - io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA; - break; - default: - png_destroy_read_struct(&rd->png_ptr, &rd->info_ptr, &rd->end_ptr); - image_thread_err(io->thread, IMAGE_ERR_READ_FAILED, "Unknown color type"); - break; - } + io->cols = rd->cols; + io->rows = rd->rows; + switch (rd->color_type) + { + case PNG_COLOR_TYPE_GRAY: + io->flags |= COLOR_SPACE_GRAYSCALE; + io->number_of_colors = 1 << 8; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + io->flags |= COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; + io->number_of_colors = 1 << 8; + break; + case PNG_COLOR_TYPE_RGB: + io->flags |= COLOR_SPACE_RGB; + io->number_of_colors = 1 << 24; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + io->number_of_colors = 1 << 24; + io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA; + break; + case PNG_COLOR_TYPE_PALETTE: + io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA; + int num_palette; + if (png_get_PLTE(rd->png_ptr, rd->info_ptr, NULL, &num_palette)) + io->number_of_colors = num_palette; + else + io->number_of_colors = 1 << rd->bit_depth; + io->has_palette = 1; + break; + default: + png_destroy_read_struct(&rd->png_ptr, &rd->info_ptr, &rd->end_ptr); + image_thread_err(io->thread, IMAGE_ERR_READ_FAILED, "Unknown color type"); + break; + } /* Success */ io->read_cancel = libpng_read_cancel; @@ -203,7 +212,7 @@ libpng_read_data(struct image_io *io) DBG("Libpng failed to read the image, longjump saved us"); png_destroy_read_struct(&rd->png_ptr, &rd->info_ptr, &rd->end_ptr); if (need_scale || !io->pool) - image_destroy(io->thread, img); + image_destroy(img); return 0; } @@ -272,14 +281,14 @@ libpng_read_data(struct image_io *io) struct image *dest = image_new(io->thread, io->cols, io->rows, io->flags, io->pool); if (!dest) { - image_destroy(io->thread, img); + image_destroy(img); return 0; } if (!image_scale(io->thread, dest, img)) { - image_destroy(io->thread, img); + image_destroy(img); if (!io->pool) - image_destroy(io->thread, dest); + image_destroy(dest); return 0; } io->image = dest; diff --git a/images/io-main.c b/images/io-main.c index 76f5db90..65f61782 100644 --- a/images/io-main.c +++ b/images/io-main.c @@ -37,7 +37,7 @@ image_io_image_destroy(struct image_io *io) { if (io->image_destroy) { - image_destroy(io->thread, io->image); + image_destroy(io->image); io->image_destroy = 0; io->image = NULL; }