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.has_palette ? (byte *)"Palette" : image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT));
+ 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);
}
else
{
MSG("%s %dx%d %s", image_format_to_extension(io.format) ? : (byte *)"?", io.cols, io.rows,
- 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 & IMAGE_CHANNELS_FORMAT));
if (cols)
if (fit_to_box)
{
#undef IMAGE_WALK_UNROLL
#undef IMAGE_WALK_DOUBLE
#undef IMAGE_WALK_EXTRA_ARGS
+#undef IMAGE_WALK_IMAGE
#undef IMAGE_WALK_PIXELS
#undef IMAGE_WALK_COLS
#undef IMAGE_WALK_ROWS
#undef IMAGE_WALK_COL_STEP
#undef IMAGE_WALK_ROW_STEP
+#undef IMAGE_WALK_SEC_IMAGE
#undef IMAGE_WALK_SEC_PIXELS
#undef IMAGE_WALK_SEC_COLS
#undef IMAGE_WALK_SEC_ROWS
};
struct image_io {
- /* 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 */
+ /* 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 ] - see enum image_io_flags */
+ u32 jpeg_quality; /* [ W] - JPEG compression quality (1..100) */
+ u32 number_of_colors; /* [ H ] - number of image colors */
/* internals */
struct image_thread *thread;
void (*read_cancel)(struct image_io *io);
};
+enum image_io_flags {
+ IMAGE_IO_IMAGE_FLAGS = 0xffff, /* [ HI ] - parameter to image new, read_header fills IMAGE_CHANNELS_FORMAT */
+ IMAGE_IO_HAS_PALETTE = 0x10000, /* [ H ] - true for image with indexed colors */
+};
+
void image_io_init(struct image_thread *it, struct image_io *io);
void image_io_cleanup(struct image_io *io);
void image_io_reset(struct image_io *io);
enum image_format image_extension_to_format(byte *extension);
enum image_format image_file_name_to_format(byte *file_name);
-/* internals */
-
-#ifdef CONFIG_IMAGES_LIBJPEG
-int libjpeg_read_header(struct image_io *io);
-int libjpeg_read_data(struct image_io *io);
-int libjpeg_write(struct image_io *io);
-#endif
-
-#ifdef CONFIG_IMAGES_LIBPNG
-int libpng_read_header(struct image_io *io);
-int libpng_read_data(struct image_io *io);
-int libpng_write(struct image_io *io);
-#endif
-
-#ifdef CONFIG_IMAGES_LIBUNGIF
-int libungif_read_header(struct image_io *io);
-int libungif_read_data(struct image_io *io);
-#endif
-
-#ifdef CONFIG_IMAGES_LIBMAGICK
-int libmagick_read_header(struct image_io *io);
-int libmagick_read_data(struct image_io *io);
-int libmagick_write(struct image_io *io);
-#endif
-
#endif
#include "lib/mempool.h"
#include "lib/fastbuf.h"
#include "images/images.h"
-
+#include "images/io-main.h"
#include <stdio.h>
#include <sys/types.h>
#include <jpeglib.h>
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 ... FIXME: use libjpeg feature to speed up downscale */
+ struct image_io_read_data_internals rdi;
+ if (unlikely(!image_io_read_data_prepare(&rdi, io, i->cinfo.image_width, i->cinfo.image_height)))
{
- image_thread_err(io->thread, IMAGE_ERR_INVALID_PIXEL_FORMAT, "Unsupported color space.");
+ jpeg_destroy_decompress(&i->cinfo);
return 0;
}
{
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)
{
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
#include "lib/mempool.h"
#include "lib/fastbuf.h"
#include "images/images.h"
+#include "images/io-main.h"
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
switch (rd->image->colorspace)
{
case GRAYColorspace:
- io->flags |= COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
+ io->flags = COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
break;
default:
- io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA;
+ 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->flags |= IMAGE_IO_HAS_PALETTE;
io->read_cancel = libmagick_read_cancel;
return 1;
break;
}
- /* Allocate image for conversion */
- int need_scale = io->cols != rd->image->columns || io->rows != rd->image->rows;
- int need_destroy = need_scale || !io->pool;
- struct image *img = need_scale ?
- image_new(io->thread, rd->image->columns, rd->image->rows, io->flags & IMAGE_CHANNELS_FORMAT, NULL) :
- image_new(io->thread, io->cols, io->rows, io->flags, io->pool);
- if (unlikely(!img))
- goto err;
+ /* Prepare the image */
+ struct image_io_read_data_internals rdi;
+ if (unlikely(!image_io_read_data_prepare(&rdi, io, rd->image->columns, rd->image->rows)))
+ {
+ libmagick_destroy_read_data(rd);
+ return 0;
+ }
/* Acquire pixels */
PixelPacket *src = (PixelPacket *)AcquireImagePixels(rd->image, 0, 0, rd->image->columns, rd->image->rows, &rd->exception);
if (unlikely(!src))
{
image_thread_err(io->thread, IMAGE_ERR_READ_FAILED, "Cannot acquire image pixels.");
- goto err;
+ libmagick_destroy_read_data(rd);
+ image_io_read_data_break(&rdi, io);
+ return 0;
}
/* Convert pixels */
- switch (img->pixel_size)
+ switch (rdi.image->pixel_size)
{
case 1:
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 1
# define IMAGE_WALK_DO_STEP do{ \
case 2:
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 2
# define IMAGE_WALK_DO_STEP do{ \
case 3:
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 3
# define IMAGE_WALK_DO_STEP do{ \
case 4:
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 4
# define IMAGE_WALK_DO_STEP do{ \
/* Free GraphicsMagick structures */
libmagick_destroy_read_data(rd);
- /* Scale image */
- if (need_scale)
- {
- struct image *img2 = image_new(io->thread, io->cols, io->rows, io->flags, io->pool);
- if (unlikely(!img2))
- goto err2;
- int result = image_scale(io->thread, img2, img);
- image_destroy(img);
- img = img2;
- need_destroy = !io->pool;
- if (unlikely(!result))
- goto err2;
- }
-
- /* Success */
- io->image = img;
- io->image_destroy = need_destroy;
- return 1;
-
- /* Free structures */
-err:
- libmagick_destroy_read_data(rd);
-err2:
- if (need_destroy)
- image_destroy(img);
- return 0;
+ /* Finish the image */
+ return image_io_read_data_finish(&rdi, io);
}
int
#include "lib/mempool.h"
#include "lib/fastbuf.h"
#include "images/images.h"
+#include "images/io-main.h"
#include <png.h>
#include <setjmp.h>
switch (rd->color_type)
{
case PNG_COLOR_TYPE_GRAY:
- io->flags |= COLOR_SPACE_GRAYSCALE;
+ 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->flags = COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
io->number_of_colors = 1 << 8;
break;
case PNG_COLOR_TYPE_RGB:
- io->flags |= COLOR_SPACE_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;
+ io->flags = COLOR_SPACE_RGB | IMAGE_ALPHA;
break;
case PNG_COLOR_TYPE_PALETTE:
- io->flags |= COLOR_SPACE_RGB | IMAGE_ALPHA;
+ io->flags = COLOR_SPACE_RGB | IMAGE_ALPHA | IMAGE_IO_HAS_PALETTE;
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);
return 0;
}
- volatile int need_scale = io->cols != rd->cols || io->rows != rd->rows;
- struct image * volatile img = need_scale ?
- image_new(io->thread, rd->cols, rd->rows, io->flags & IMAGE_PIXEL_FORMAT, NULL) :
- image_new(io->thread, rd->cols, rd->rows, io->flags, io->pool);
- if (!img)
+ /* Prepare the image */
+ struct image_io_read_data_internals rdi;
+ if (unlikely(!image_io_read_data_prepare(&rdi, io, rd->cols, rd->rows)))
{
png_destroy_read_struct(&rd->png_ptr, &rd->info_ptr, &rd->end_ptr);
return 0;
{
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(img);
+ image_io_read_data_break(&rdi, io);
return 0;
}
/* Read image data */
DBG("Reading image data");
+ struct image *img = rdi.image;
byte *pixels = img->pixels;
png_bytep rows[img->rows];
for (uns r = 0; r < img->rows; r++, pixels += img->row_size)
/* Destroy libpng read structure */
png_destroy_read_struct(&rd->png_ptr, &rd->info_ptr, &rd->end_ptr);
- /* Scale and store the resulting image */
- if (need_scale)
- {
- 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;
- }
- io->image = dest;
- }
- else
- io->image = img;
- io->image_destroy = !io->pool;
-
- return 1;
+ /* Finish the image */
+ return image_io_read_data_finish(&rdi, io);
}
int
#include "lib/mempool.h"
#include "lib/fastbuf.h"
#include "images/images.h"
+#include "images/io-main.h"
#include <gif_lib.h>
static int
}
io->cols = image->ImageDesc.Width;
io->rows = image->ImageDesc.Height;
- io->has_palette = 1;
io->number_of_colors = color_map->ColorCount;
- io->flags = COLOR_SPACE_RGB;
+ io->flags = COLOR_SPACE_RGB | IMAGE_IO_HAS_PALETTE;
if ((uns)gif->SBackGroundColor < (uns)color_map->ColorCount)
io->flags |= IMAGE_ALPHA;
GifFileType *gif = io->read_data;
SavedImage *image = gif->SavedImages;
- /* Allocate image */
- int need_scale = io->cols != (uns)image->ImageDesc.Width || io->rows != (uns)image->ImageDesc.Height;
- int need_destroy = need_scale || !io->pool;
- struct image *img = need_scale ?
- image_new(io->thread, image->ImageDesc.Width, image->ImageDesc.Height, io->flags & IMAGE_CHANNELS_FORMAT, NULL) :
- image_new(io->thread, io->cols, io->rows, io->flags, io->pool);
- if (unlikely(!img))
- goto err;
+ /* Prepare image */
+ struct image_io_read_data_internals rdi;
+ if (unlikely(!image_io_read_data_prepare(&rdi, io, image->ImageDesc.Width, image->ImageDesc.Height)))
+ {
+ DGifCloseFile(gif);
+ return 0;
+ }
/* Get pixels and palette */
byte *pixels = (byte *)image->RasterBits;
ColorMapObject *color_map = image->ImageDesc.ColorMap ? : gif->SColorMap;
GifColorType *palette = color_map->Colors;
uns background = gif->SBackGroundColor;
- byte *img_end = img->pixels + img->image_size;
+ byte *img_end = rdi.image->pixels + rdi.image->image_size;
/* Handle deinterlacing */
uns dein_step, dein_next;
if (image->ImageDesc.Interlace)
- dein_step = dein_next = img->row_size << 3;
+ dein_step = dein_next = rdi.image->row_size << 3;
else
- dein_step = dein_next = img->row_size;
+ dein_step = dein_next = rdi.image->row_size;
/* Convert pixels */
- switch (img->pixel_size)
+ switch (rdi.image->pixel_size)
{
case 1:
{
# define DO_ROW_END do{ \
walk_row_start += dein_step; \
if (walk_row_start > img_end) \
- { uns n = dein_next >> 1; walk_row_start = img->pixels + n, dein_step = dein_next; dein_next = n; } \
+ { uns n = dein_next >> 1; walk_row_start = rdi.image->pixels + n, dein_step = dein_next; dein_next = n; } \
}while(0)
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 1
# define IMAGE_WALK_ROW_STEP 0
pal[background * 2 + 1] = 0;
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 2
# define IMAGE_WALK_ROW_STEP 0
bzero(pal_pos, pal_end - pal_pos);
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 3
# define IMAGE_WALK_ROW_STEP 0
pal[background * 4 + 3] = 0;
# define IMAGE_WALK_PREFIX(x) walk_##x
# define IMAGE_WALK_INLINE
-# define IMAGE_WALK_IMAGE img
+# define IMAGE_WALK_IMAGE (rdi.image)
# define IMAGE_WALK_UNROLL 4
# define IMAGE_WALK_COL_STEP 4
# define IMAGE_WALK_ROW_STEP 0
/* Destroy libungif structure */
DGifCloseFile(gif);
- /* Scale image */
- if (need_scale)
- {
- struct image *img2 = image_new(io->thread, io->cols, io->rows, io->flags, io->pool);
- if (unlikely(!img2))
- goto err2;
- int result = image_scale(io->thread, img2, img);
- image_destroy(img);
- img = img2;
- need_destroy = !io->pool;
- if (unlikely(!result))
- goto err2;
- }
-
- /* Success */
- io->image = img;
- io->image_destroy = need_destroy;
- return 1;
-
- /* Free structures */
-err:
- DGifCloseFile(gif);
-err2:
- if (need_destroy)
- image_destroy(img);
- return 0;
+ /* Finish image */
+ return image_io_read_data_finish(&rdi, io);
}
#include "lib/lib.h"
#include "images/images.h"
+#include "images/io-main.h"
#include <string.h>
void