#include "images/images.h"
#include "images/color.h"
+#include <string.h>
+
+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 };
#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 {
-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\
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)
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];
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)
{
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);
}
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;
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:
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;
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
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;
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;
}
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;
}
#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,
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 */
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 {
* of the GNU Lesser General Public License.
*/
-#undef LOCAL_DEBUG
+#define LOCAL_DEBUG
#include "lib/lib.h"
#include "lib/mempool.h"
{
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;
}
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.");
/* 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 */
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);
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);