X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=images%2Fio-libjpeg.c;h=876c1720131e0d36c07bcc387d18885c1464bb41;hb=731cb9f2c5a321a96bf36e3278382bb9ca26c72e;hp=dddfd79f7dfb8d71363fa926707d1c246f31137e;hpb=35d602a8f8676b8988eca13086c63f2026c1b952;p=libucw.git diff --git a/images/io-libjpeg.c b/images/io-libjpeg.c index dddfd79f..876c1720 100644 --- a/images/io-libjpeg.c +++ b/images/io-libjpeg.c @@ -13,7 +13,7 @@ #include "lib/mempool.h" #include "lib/fastbuf.h" #include "images/images.h" - +#include "images/io-main.h" #include #include #include @@ -66,11 +66,11 @@ libjpeg_write_error_exit(j_common_ptr cinfo) static void libjpeg_emit_message(j_common_ptr cinfo UNUSED, int msg_level UNUSED) { -#ifdef LOCAL_DEBUG +#ifdef LOCAL_DEBUG byte buf[JMSG_LENGTH_MAX]; cinfo->err->format_message(cinfo, buf); DBG("libjpeg_emit_message(): [%d] %s", msg_level, buf); -#endif +#endif if (unlikely(msg_level == -1)) longjmp(((struct libjpeg_err *)(cinfo)->err)->setjmp_buf, 1); } @@ -241,8 +241,8 @@ libjpeg_read_data(struct image_io *io) DBG("libjpeg_read_data()"); struct libjpeg_read_internals *i = io->read_data; - - /* Select color space */ + + /* Select color space */ switch (io->flags & IMAGE_COLOR_SPACE) { case COLOR_SPACE_GRAYSCALE: @@ -257,28 +257,45 @@ libjpeg_read_data(struct image_io *io) return 0; } - /* Allocate the image... FIXME: use libjpeg feature to speed up downscale */ - volatile int need_scale = io->cols != i->cinfo.image_width || io->rows != i->cinfo.image_height; - struct image * volatile img = need_scale ? - image_new(io->thread, i->cinfo.image_width, i->cinfo.image_height, io->flags & IMAGE_PIXEL_FORMAT, NULL) : - image_new(io->thread, i->cinfo.image_width, i->cinfo.image_height, io->flags, io->pool); - if (!img) + /* Prepare the image */ + struct image_io_read_data_internals rdi; + if (io->cols <= (i->cinfo.image_width >> 3) && io->rows <= (i->cinfo.image_height >> 3)) + { + DBG("Scaling to 1/8"); + i->cinfo.scale_num = 1; + i->cinfo.scale_denom = 8; + } + else if (io->cols <= (i->cinfo.image_width >> 2) && io->rows <= (i->cinfo.image_height >> 2)) + { + DBG("Scaling to 1/4"); + i->cinfo.scale_num = 1; + i->cinfo.scale_denom = 4; + } + else if (io->cols <= (i->cinfo.image_width >> 1) && io->rows <= (i->cinfo.image_height >> 1)) + { + DBG("Scaling to 1/2"); + i->cinfo.scale_num = 1; + i->cinfo.scale_denom = 2; + } + jpeg_calc_output_dimensions(&i->cinfo); + DBG("Output dimensions %ux%u", (uns)i->cinfo.output_width, (uns)i->cinfo.output_height); + if (unlikely(!image_io_read_data_prepare(&rdi, io, i->cinfo.output_width, i->cinfo.output_height, io->flags))) { - image_thread_err(io->thread, IMAGE_ERR_INVALID_PIXEL_FORMAT, "Unsupported color space."); + jpeg_destroy_decompress(&i->cinfo); return 0; } - + /* Setup fallback */ if (setjmp(i->err.setjmp_buf)) { DBG("Libjpeg failed to read the image, longjump saved us"); jpeg_destroy_decompress(&i->cinfo); - if (need_scale || !io->pool) - image_destroy(img); + image_io_read_data_break(&rdi, io); return 0; } /* Decompress the image */ + struct image *img = rdi.image; jpeg_start_decompress(&i->cinfo); switch (img->pixel_size) { @@ -294,15 +311,17 @@ libjpeg_read_data(struct image_io *io) } } break; - /* garscale with alpha */ + /* grayscale with alpha */ case 2: { byte buf[img->cols], *src; +# define IMAGE_WALK_PREFIX(x) walk_##x # define IMAGE_WALK_INLINE +# define IMAGE_WALK_IMAGE img # define IMAGE_WALK_UNROLL 4 # define IMAGE_WALK_COL_STEP 2 # define IMAGE_WALK_DO_ROW_START do{ src = buf; jpeg_read_scanlines(&i->cinfo, (JSAMPLE **)&src, 1); }while(0) -# define IMAGE_WALK_DO_STEP do{ pos[0] = *src++; pos[1] = 255; }while(0) +# define IMAGE_WALK_DO_STEP do{ walk_pos[0] = *src++; walk_pos[1] = 255; }while(0) # include "images/image-walk.h" } break; @@ -310,11 +329,13 @@ libjpeg_read_data(struct image_io *io) case 4: { byte buf[img->cols * 3], *src; +# define IMAGE_WALK_PREFIX(x) walk_##x # define IMAGE_WALK_INLINE +# define IMAGE_WALK_IMAGE img # define IMAGE_WALK_UNROLL 4 # define IMAGE_WALK_COL_STEP 4 # define IMAGE_WALK_DO_ROW_START do{ src = buf; jpeg_read_scanlines(&i->cinfo, (JSAMPLE **)&src, 1); }while(0) -# define IMAGE_WALK_DO_STEP do{ *(u32 *)pos = *(u32 *)src; pos[3] = 255; src += 3; }while(0) +# define IMAGE_WALK_DO_STEP do{ *(u32 *)walk_pos = *(u32 *)src; walk_pos[3] = 255; src += 3; }while(0) # include "images/image-walk.h" } break; @@ -322,37 +343,13 @@ libjpeg_read_data(struct image_io *io) ASSERT(0); } ASSERT(i->cinfo.output_scanline == i->cinfo.output_height); - + /* Destroy libjpeg object */ jpeg_finish_decompress(&i->cinfo); jpeg_destroy_decompress(&i->cinfo); - /* Scale result if necessary */ - if (need_scale) - { - DBG("Scaling image"); - struct image *dest = image_new(io->thread, io->cols, io->rows, io->flags, io->pool); - if (!dest) - { - image_destroy(img); - return 0; - } - if (!(image_scale(io->thread, dest, img))) - { - image_destroy(img); - if (!io->pool) - image_destroy(dest); - return 0; - } - image_destroy(img); - io->image = dest; - } - else - io->image = img; - io->image_destroy = !io->pool; - - DBG("Image readed"); - return 1; + /* Finish the image */ + return image_io_read_data_finish(&rdi, io); } int @@ -375,7 +372,7 @@ libjpeg_write(struct image_io *io) return 0; } jpeg_create_compress(&i.cinfo); - + /* Initialize destination manager */ i.cinfo.dest = &i.dest; i.dest.init_destination = libjpeg_init_destination; @@ -425,11 +422,13 @@ libjpeg_write(struct image_io *io) case 2: { byte buf[img->cols], *dest = buf; +# define IMAGE_WALK_PREFIX(x) walk_##x # define IMAGE_WALK_INLINE +# define IMAGE_WALK_IMAGE img # define IMAGE_WALK_UNROLL 4 # define IMAGE_WALK_COL_STEP 2 # define IMAGE_WALK_DO_ROW_END do{ dest = buf; jpeg_write_scanlines(&i.cinfo, (JSAMPLE **)&dest, 1); }while(0) -# define IMAGE_WALK_DO_STEP do{ *dest++ = pos[0]; }while(0) +# define IMAGE_WALK_DO_STEP do{ *dest++ = walk_pos[0]; }while(0) # include "images/image-walk.h" } break; @@ -437,11 +436,13 @@ libjpeg_write(struct image_io *io) case 4: { byte buf[img->cols * 3], *dest = buf; +# define IMAGE_WALK_PREFIX(x) walk_##x # define IMAGE_WALK_INLINE +# define IMAGE_WALK_IMAGE img # define IMAGE_WALK_UNROLL 4 # define IMAGE_WALK_COL_STEP 4 # define IMAGE_WALK_DO_ROW_END do{ dest = buf; jpeg_write_scanlines(&i.cinfo, (JSAMPLE **)&dest, 1); }while(0) -# define IMAGE_WALK_DO_STEP do{ *dest++ = pos[0]; *dest++ = pos[1]; *dest++ = pos[2]; }while(0) +# define IMAGE_WALK_DO_STEP do{ *dest++ = walk_pos[0]; *dest++ = walk_pos[1]; *dest++ = walk_pos[2]; }while(0) # include "images/image-walk.h" } break;