From: Pavel Charvat Date: Wed, 1 Nov 2006 13:38:11 +0000 (+0100) Subject: slightly changed dealing with color spaces X-Git-Tag: holmes-import~507^2~31 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=f784f9b6365d92dac7b10ab2e589d02c7445e987;p=libucw.git slightly changed dealing with color spaces (I will add CMYK -> RGB conversion soon ... bug #2819) --- diff --git a/images/color.c b/images/color.c index 8ea60228..7dd3773c 100644 --- a/images/color.c +++ b/images/color.c @@ -14,6 +14,54 @@ #include "images/images.h" #include "images/color.h" +#include + +uns color_space_channels[COLOR_SPACE_MAX] = { + [COLOR_SPACE_UNKNOWN] = 0, + [COLOR_SPACE_UNKNOWN_1] = 1, + [COLOR_SPACE_UNKNOWN_2] = 2, + [COLOR_SPACE_UNKNOWN_3] = 3, + [COLOR_SPACE_UNKNOWN_4] = 4, + [COLOR_SPACE_GRAYSCALE] = 1, + [COLOR_SPACE_RGB] = 3, + [COLOR_SPACE_XYZ] = 3, + [COLOR_SPACE_LAB] = 3, + [COLOR_SPACE_YCBCR] = 3, + [COLOR_SPACE_CMYK] = 4, + [COLOR_SPACE_YCCK] = 4, +}; + +byte *color_space_name[COLOR_SPACE_MAX] = { + [COLOR_SPACE_UNKNOWN] = "Unknown", + [COLOR_SPACE_UNKNOWN_1] = "1-channel", + [COLOR_SPACE_UNKNOWN_2] = "2-channels", + [COLOR_SPACE_UNKNOWN_3] = "3-channels", + [COLOR_SPACE_UNKNOWN_4] = "4-channels", + [COLOR_SPACE_GRAYSCALE] = "Grayscale", + [COLOR_SPACE_RGB] = "RGB", + [COLOR_SPACE_XYZ] = "XYZ", + [COLOR_SPACE_LAB] = "LAB", + [COLOR_SPACE_YCBCR] = "YCbCr", + [COLOR_SPACE_CMYK] = "CMYK", + [COLOR_SPACE_YCCK] = "YCCK", +}; + +byte * +color_space_id_to_name(uns id) +{ + ASSERT(id < COLOR_SPACE_MAX); + return color_space_name[id]; +} + +uns +color_space_name_to_id(byte *name) +{ + for (uns i = 1; i < COLOR_SPACE_MAX; i++) + if (!strcasecmp(name, color_space_name[i])) + return i; + return 0; +} + struct color color_black = { .color_space = COLOR_SPACE_GRAYSCALE }; struct color color_white = { .c = { 255 }, .color_space = COLOR_SPACE_GRAYSCALE }; diff --git a/images/color.h b/images/color.h index 8c87e87c..7ec32acc 100644 --- a/images/color.h +++ b/images/color.h @@ -27,19 +27,30 @@ #include "images/images.h" -// A comparison of four multimedia RGB spaces, Danny Pascale - enum { COLOR_SPACE_UNKNOWN = 0, + COLOR_SPACE_UNKNOWN_1 = 1, + COLOR_SPACE_UNKNOWN_2 = 2, + COLOR_SPACE_UNKNOWN_3 = 3, + COLOR_SPACE_UNKNOWN_4 = 4, + COLOR_SPACE_UNKNOWN_MAX = 4, COLOR_SPACE_GRAYSCALE, COLOR_SPACE_RGB, COLOR_SPACE_XYZ, COLOR_SPACE_LAB, COLOR_SPACE_LUV, COLOR_SPACE_YCBCR, + COLOR_SPACE_CMYK, + COLOR_SPACE_YCCK, COLOR_SPACE_MAX }; +extern uns color_space_channels[COLOR_SPACE_MAX]; +extern byte *color_space_name[COLOR_SPACE_MAX]; + +byte *color_space_id_to_name(uns id); +uns color_space_name_to_id(byte *name); + /* Color spaces in the CIE 1931 chromacity diagram */ struct color_space_chromacity_info { diff --git a/images/image-tool.c b/images/image-tool.c index 3e40bcb9..758000ab 100644 --- a/images/image-tool.c +++ b/images/image-tool.c @@ -29,7 +29,7 @@ Usage: image-tool [options] infile [outfile]\n\ -F --output-format output image format\n\ -s --size force output dimensions (100x200)\n\ -b --fit-to-box scale to fit the box (100x200)\n\ --c --colorspace force output colorspace (Gray, GrayAlpha, RGB, RGBAlpha)\n\ +-c --colorspace force output colorspace (Grayscale, Grayscale+Alpha, RGB, RGB+Alpha, ...)\n\ -Q --jpeg-quality JPEG quality (1..100)\n\ -g --background background color (hexadecimal RRGGBB)\n\ -G --default-background background applied only if the image contains no background info (RRGGBB, default=FFFFFF)\n\ @@ -168,6 +168,7 @@ main(int argc, char **argv) die("Cannot initialize image I/O"); MSG("Reading %s", input_file_name); + byte cs_buf[IMAGE_CHANNELS_FORMAT_MAX_SIZE]; io.fastbuf = bopen(input_file_name, O_RDONLY, 1 << 18); io.format = input_format ? : image_file_name_to_format(input_file_name); if (exif) @@ -178,8 +179,8 @@ 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", (io.flags & IMAGE_IO_HAS_PALETTE) ? (byte *)"Palette" : image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); - printf("NumColors: %d\n", io.number_of_colors); + printf("Colorspace: %s\n", (io.flags & IMAGE_IO_HAS_PALETTE) ? (byte *)"Palette" : image_channels_format_to_name(io.flags, cs_buf)); + printf("NumColors: %u\n", io.number_of_colors); if (io.background_color.color_space) { byte rgb[3]; @@ -192,7 +193,7 @@ main(int argc, char **argv) else { MSG("%s %dx%d %s", image_format_to_extension(io.format) ? : (byte *)"?", io.cols, io.rows, - (io.flags & IMAGE_IO_HAS_PALETTE) ? (byte *)"Palette" : image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT)); + (io.flags & IMAGE_IO_HAS_PALETTE) ? (byte *)"Palette" : image_channels_format_to_name(io.flags, cs_buf)); if (cols) if (fit_to_box) { @@ -221,7 +222,7 @@ main(int argc, char **argv) io.fastbuf = bopen(output_file_name, O_WRONLY | O_CREAT | O_TRUNC, 1 << 18); io.format = output_format ? : image_file_name_to_format(output_file_name); 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)); + image_channels_format_to_name(io.flags, cs_buf)); TRY(image_io_write(&io)); bclose(io.fastbuf); } diff --git a/images/image.c b/images/image.c index e42b06c1..26445aa3 100644 --- a/images/image.c +++ b/images/image.c @@ -20,18 +20,7 @@ static inline uns flags_to_pixel_size(uns flags) { - uns pixel_size; - switch (flags & IMAGE_COLOR_SPACE) - { - case COLOR_SPACE_GRAYSCALE: - pixel_size = 1; - break; - case COLOR_SPACE_RGB: - pixel_size = 3; - break; - default: - ASSERT(0); - } + uns pixel_size = color_space_channels[flags & IMAGE_COLOR_SPACE]; if (flags & IMAGE_ALPHA) pixel_size++; return pixel_size; @@ -48,9 +37,14 @@ image_new(struct image_context *ctx, uns cols, uns rows, uns flags, struct mempo return NULL; } struct image *img; - uns pixel_size, row_pixels_size, row_size, align; - pixel_size = flags_to_pixel_size(flags); - switch (pixel_size) + uns channels, pixel_size, row_pixels_size, row_size, align; + pixel_size = channels = flags_to_pixel_size(flags); + if (!channels || channels > 4) + { + IMAGE_ERROR(ctx, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Invalid number of color channels"); + return NULL; + } + switch (channels) { case 1: case 2: @@ -90,6 +84,7 @@ image_new(struct image_context *ctx, uns cols, uns rows, uns flags, struct mempo byte *p = (byte *)img + sizeof(struct image); img->pixels = ALIGN_PTR(p, IMAGE_SSE_ALIGN_SIZE); img->flags = flags; + img->channels = channels; img->pixel_size = pixel_size; img->cols = cols; img->rows = rows; @@ -110,10 +105,12 @@ image_clone(struct image_context *ctx, struct image *src, uns flags, struct memp flags |= src->flags & IMAGE_CHANNELS_FORMAT; if (!(img = image_new(ctx, src->cols, src->rows, flags, pool))) return NULL; + ASSERT(src->channels == img->channels); if (img->image_size) { if (src->pixel_size != img->pixel_size) /* conversion between aligned and unaligned RGB */ { + ASSERT(src->channels == 3); # define IMAGE_WALK_PREFIX(x) walk_##x # define IMAGE_WALK_INLINE # define IMAGE_WALK_IMAGE img @@ -175,7 +172,7 @@ image_init_matrix(struct image_context *ctx, struct image *img, byte *pixels, un img->pixels = pixels; img->cols = cols; img->rows = rows; - img->pixel_size = flags_to_pixel_size(flags); + img->pixel_size = img->channels = flags_to_pixel_size(flags); img->row_size = row_size; img->row_pixels_size = cols * img->pixel_size; img->image_size = rows * row_size; @@ -191,7 +188,7 @@ image_init_subimage(struct image_context *ctx UNUSED, struct image *img, struct img->pixels = src->pixels + left * src->pixel_size + top * src->row_size; img->cols = cols; img->rows = rows; - img->pixel_size = src->pixel_size; + img->pixel_size = img->channels = src->pixel_size; img->row_size = src->row_size; img->row_pixels_size = cols * src->pixel_size; img->image_size = src->row_size * rows; @@ -201,45 +198,30 @@ image_init_subimage(struct image_context *ctx UNUSED, struct image *img, struct } byte * -color_space_to_name(uns cs) +image_channels_format_to_name(uns format, byte *buf) { - return image_channels_format_to_name(cs); -} - -byte * -image_channels_format_to_name(uns format) -{ - switch (format) - { - case COLOR_SPACE_GRAYSCALE: - return "Gray"; - case COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA: - return "GrayAlpha"; - case COLOR_SPACE_RGB: - return "RGB"; - case COLOR_SPACE_RGB | IMAGE_ALPHA: - return "RGBAlpha"; - default: - return NULL; - } + byte *cs_name = color_space_id_to_name(format & IMAGE_COLOR_SPACE); + uns l = strlen(cs_name); + memcpy(buf, cs_name, l + 1); + if (format & IMAGE_ALPHA) + strcpy(buf + l, "+Alpha"); + return buf; } uns image_name_to_channels_format(byte *name) { - if (!strcasecmp(name, "gray")) - return COLOR_SPACE_GRAYSCALE; - if (!strcasecmp(name, "grayscale")) - return COLOR_SPACE_GRAYSCALE; - if (!strcasecmp(name, "grayalpha")) - return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; - if (!strcasecmp(name, "grayscalealpha")) - return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA; - if (!strcasecmp(name, "rgb")) - return COLOR_SPACE_RGB; - if (!strcasecmp(name, "rgbalpha")) - return COLOR_SPACE_RGB | IMAGE_ALPHA; - if (!strcasecmp(name, "rgba")) - return COLOR_SPACE_RGB | IMAGE_ALPHA; + uns i; + if (i = color_space_name_to_id(name)) + return i; + uns l = strlen(name); + if (l > 6 && !strcasecmp(name + l - 5, "+alpha")) + { + byte buf[l + 1]; + memcpy(buf, name, l - 6); + buf[l - 6] = 0; + if (i = color_space_name_to_id(name)) + return i; + } return 0; } diff --git a/images/images.h b/images/images.h index dbaa055c..f35caf59 100644 --- a/images/images.h +++ b/images/images.h @@ -55,12 +55,12 @@ extern uns image_max_bytes; /* ImageLib.ImageMaxBytes */ #define IMAGE_SSE_ALIGN_SIZE 16 enum image_flag { - IMAGE_COLOR_SPACE = 0x7, /* mask for enum color_space */ - IMAGE_ALPHA = 0x8, /* alpha channel */ - IMAGE_PIXELS_ALIGNED = 0x10, /* align pixel size to the nearest power of two */ - IMAGE_SSE_ALIGNED = 0x20, /* align scanlines to multiples of 16 bytes (both start and size) */ - IMAGE_NEED_DESTROY = 0x40, /* image is allocated with xmalloc */ - IMAGE_GAPS_PROTECTED = 0x80, /* cannot access gaps between rows */ + IMAGE_COLOR_SPACE = 0xf, /* mask for enum color_space */ + IMAGE_ALPHA = 0x10, /* alpha channel */ + IMAGE_PIXELS_ALIGNED = 0x20, /* align pixel size to the nearest power of two */ + IMAGE_SSE_ALIGNED = 0x40, /* align scanlines to multiples of 16 bytes (both start and size) */ + IMAGE_NEED_DESTROY = 0x80, /* image is allocated with xmalloc */ + IMAGE_GAPS_PROTECTED = 0x100, /* cannot access gaps between rows */ IMAGE_CHANNELS_FORMAT = IMAGE_COLOR_SPACE | IMAGE_ALPHA, IMAGE_PIXEL_FORMAT = IMAGE_CHANNELS_FORMAT | IMAGE_PIXELS_ALIGNED, IMAGE_ALIGNED = IMAGE_PIXELS_ALIGNED | IMAGE_SSE_ALIGNED, @@ -73,6 +73,7 @@ struct image { unused bytes after the buffer (possible optimizations) */ uns cols; /* number of columns */ uns rows; /* number of rows */ + uns channels; /* number of color channels */ uns pixel_size; /* size of pixel in bytes (1, 2, 3 or 4) */ uns row_size; /* scanline size in bytes */ uns row_pixels_size; /* scanline size in bytes excluding rows gaps */ @@ -93,8 +94,8 @@ image_dimensions_valid(uns cols, uns rows) return cols && rows && cols <= image_max_dim && rows <= image_max_dim; } -byte *color_space_to_name(uns cs); -byte *image_channels_format_to_name(uns format); +#define IMAGE_CHANNELS_FORMAT_MAX_SIZE 128 +byte *image_channels_format_to_name(uns format, byte *buf); uns image_name_to_channels_format(byte *name); struct color { diff --git a/images/io-libjpeg.c b/images/io-libjpeg.c index 1d3d37c5..f4a72e29 100644 --- a/images/io-libjpeg.c +++ b/images/io-libjpeg.c @@ -7,7 +7,7 @@ * of the GNU Lesser General Public License. */ -#undef LOCAL_DEBUG +#define LOCAL_DEBUG #include "lib/lib.h" #include "lib/mempool.h" @@ -294,16 +294,38 @@ libjpeg_read_header(struct image_io *io) { case JCS_GRAYSCALE: io->flags = COLOR_SPACE_GRAYSCALE; - io->number_of_colors = 1 << 8; break; + case JCS_RGB: + io->flags = COLOR_SPACE_RGB; + break; + case JCS_YCbCr: + io->flags = COLOR_SPACE_YCBCR; + break; + case JCS_CMYK: + io->flags = COLOR_SPACE_CMYK; + break; + case JCS_YCCK: + io->flags = COLOR_SPACE_YCCK; + break; default: - io->flags = COLOR_SPACE_RGB; - io->number_of_colors = 1 << 24; - break; + if (unlikely(i->cinfo.num_components < 1 || i->cinfo.num_components > 4)) + { + jpeg_destroy_decompress(&i->cinfo); + IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Invalid color space."); + return 0; + } + io->flags = COLOR_SPACE_UNKNOWN + i->cinfo.num_components; + break; + } + if (unlikely(i->cinfo.num_components != (int)color_space_channels[io->flags])) + { + jpeg_destroy_decompress(&i->cinfo); + IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Invalid number of color channels."); + return 0; } io->cols = i->cinfo.image_width; io->rows = i->cinfo.image_height; - + io->number_of_colors = (i->cinfo.num_components < 4) ? (1U << (i->cinfo.num_components * 8)) : 0xffffffff; io->read_cancel = libjpeg_read_cancel; return 1; } @@ -324,6 +346,15 @@ libjpeg_read_data(struct image_io *io) case COLOR_SPACE_RGB: i->cinfo.out_color_space = JCS_RGB; break; + case COLOR_SPACE_YCBCR: + i->cinfo.out_color_space = JCS_YCbCr; + break; + case COLOR_SPACE_CMYK: + i->cinfo.out_color_space = JCS_CMYK; + break; + case COLOR_SPACE_YCCK: + i->cinfo.out_color_space = JCS_YCCK; + break; default: jpeg_destroy_decompress(&i->cinfo); IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Unsupported color space."); @@ -370,51 +401,53 @@ libjpeg_read_data(struct image_io *io) /* Decompress the image */ struct image *img = rdi.image; jpeg_start_decompress(&i->cinfo); - switch (img->pixel_size) + if ((int)img->pixel_size == i->cinfo.num_components) { - /* grayscale or RGB */ - case 1: - case 3: - { - byte *pixels = img->pixels; - for (uns r = img->rows; r--; ) - { - jpeg_read_scanlines(&i->cinfo, (JSAMPLE **)&pixels, 1); - pixels += img->row_size; - } - } - break; - /* 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{ walk_pos[0] = *src++; walk_pos[1] = 255; }while(0) -# include "images/image-walk.h" - } - break; - /* RGBA or aligned RGB */ - 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 *)walk_pos = *(u32 *)src; walk_pos[3] = 255; src += 3; }while(0) -# include "images/image-walk.h" + byte *pixels = img->pixels; + for (uns r = img->rows; r--; ) + { + jpeg_read_scanlines(&i->cinfo, (JSAMPLE **)&pixels, 1); + pixels += img->row_size; + } + } + else + { + switch (img->pixel_size) + { + case 2: /* Grayscale -> Grayscale+Alpha */ + { + ASSERT(i->cinfo.num_components == 1); + 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{ walk_pos[0] = *src++; walk_pos[1] = 255; }while(0) +# include "images/image-walk.h" + } + break; + case 4: /* * -> *+Alpha or aligned * */ + { + ASSERT(i->cinfo.num_components == 3); + 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 *)walk_pos = *(u32 *)src; walk_pos[3] = 255; src += 3; }while(0) +# include "images/image-walk.h" + } + break; + default: + ASSERT(0); } - break; - default: - ASSERT(0); + } + ASSERT(i->cinfo.output_scanline == i->cinfo.output_height); /* Destroy libjpeg object */ @@ -459,18 +492,26 @@ libjpeg_write(struct image_io *io) switch (img->flags & IMAGE_COLOR_SPACE) { case COLOR_SPACE_GRAYSCALE: - i.cinfo.input_components = 1; i.cinfo.in_color_space = JCS_GRAYSCALE; break; case COLOR_SPACE_RGB: - i.cinfo.input_components = 3; i.cinfo.in_color_space = JCS_RGB; break; + case COLOR_SPACE_YCBCR: + i.cinfo.in_color_space = JCS_YCbCr; + break; + case COLOR_SPACE_CMYK: + i.cinfo.in_color_space = JCS_CMYK; + break; + case COLOR_SPACE_YCCK: + i.cinfo.in_color_space = JCS_YCCK; + break; default: jpeg_destroy_compress(&i.cinfo); IMAGE_ERROR(io->context, IMAGE_ERROR_INVALID_PIXEL_FORMAT, "Unsupported pixel format."); return 0; } + i.cinfo.input_components = color_space_channels[img->flags & IMAGE_COLOR_SPACE]; jpeg_set_defaults(&i.cinfo); if (io->jpeg_quality) jpeg_set_quality(&i.cinfo, MIN(io->jpeg_quality, 100), 1); @@ -490,50 +531,50 @@ libjpeg_write(struct image_io *io) DBG("Writing EXIF"); jpeg_write_marker(&i.cinfo, JPEG_APP0 + 1, io->exif_data, io->exif_size); } - switch (img->pixel_size) + if ((int)img->pixel_size == i.cinfo.input_components) { - /* grayscale or RGB */ - case 1: - case 3: - { - byte *pixels = img->pixels; - for (uns r = img->rows; r--; ) + byte *pixels = img->pixels; + for (uns r = img->rows; r--; ) + { + jpeg_write_scanlines(&i.cinfo, (JSAMPLE **)&pixels, 1); + pixels += img->row_size; + } + } + else + { + switch (img->pixel_size) + { + case 2: /* Grayscale+Alpha -> Grayscale */ { - jpeg_write_scanlines(&i.cinfo, (JSAMPLE **)&pixels, 1); - pixels += img->row_size; - } - } - break; - /* grayscale with alpha (ignore alpha) */ - 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++ = walk_pos[0]; }while(0) -# include "images/image-walk.h" - } - break; - /* RGBA (ignore alpha) or aligned RGB */ - 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++ = walk_pos[0]; *dest++ = walk_pos[1]; *dest++ = walk_pos[2]; }while(0) -# include "images/image-walk.h" + ASSERT(i.cinfo.input_components == 1); + 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++ = walk_pos[0]; }while(0) +# include "images/image-walk.h" + break; + } + case 4: /* *+Alpha or aligned * -> * */ + { + ASSERT(i.cinfo.input_components == 3); + 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++ = walk_pos[0]; *dest++ = walk_pos[1]; *dest++ = walk_pos[2]; }while(0) +# include "images/image-walk.h" + break; + } + default: + ASSERT(0); } - break; - default: - ASSERT(0); } ASSERT(i.cinfo.next_scanline == i.cinfo.image_height); jpeg_finish_compress(&i.cinfo);