image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool *pool)
{
DBG("image_new(cols=%u rows=%u flags=0x%x pool=%p)", cols, rows, flags, pool);
- flags &= IMAGE_PIXEL_FORMAT | IMAGE_SSE_ALIGNED;
+ flags &= IMAGE_NEW_FLAGS;
if (unlikely(!image_dimensions_valid(cols, rows)))
{
image_thread_err_format(it, IMAGE_ERR_INVALID_DIMENSIONS, "Invalid image dimensions (%ux%u)", cols, rows);
{
DBG("image_clone(src=%p flags=0x%x pool=%p)", src, src->flags, pool);
struct image *img;
- flags &= ~IMAGE_CHANNELS_FORMAT;
+ flags &= IMAGE_NEW_FLAGS & ~IMAGE_CHANNELS_FORMAT;
flags |= src->flags & IMAGE_CHANNELS_FORMAT;
if (!(img = image_new(it, src->cols, src->rows, flags, pool)))
return NULL;
img->rows = rows;
img->row_size = row_size;
img->image_size = rows * row_size;
- img->flags = flags & (IMAGE_PIXEL_FORMAT | IMAGE_SSE_ALIGNED);
+ img->flags = flags & (IMAGE_NEW_FLAGS | IMAGE_GAPS_PROTECTED);
return 1;
}
img->rows = rows;
img->row_size = src->row_size;
img->image_size = src->row_size * rows;
- img->flags = src->flags & ~IMAGE_NEED_DESTROY;
+ img->flags = src->flags & IMAGE_NEW_FLAGS;
+ img->flags |= IMAGE_GAPS_PROTECTED;
return 1;
}
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 write to 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,
+ IMAGE_NEW_FLAGS = IMAGE_PIXEL_FORMAT | IMAGE_SSE_ALIGNED,
+ IMAGE_INTERNAL_FLAGS = IMAGE_NEED_DESTROY | IMAGE_GAPS_PROTECTED,
};
struct image {
u32 rows; /* number of rows */
u32 pixel_size; /* size of pixel (1, 2, 3 or 4) */
u32 row_size; /* scanline size in bytes */
- u32 image_size; /* rows * rows_size */
+ u32 image_size; /* rows * row_size */
u32 flags; /* enum image_flag */
};
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 *img); /* only with NULL mempool */
+void image_destroy(struct image *img);
void image_clear(struct image_thread *it, struct image *img);
int image_init_matrix(struct image_thread *it, struct image *img, byte *pixels, uns cols, uns rows, uns row_size, uns flags);
int image_init_subimage(struct image_thread *it, struct image *img, struct image *src, uns left, uns top, uns cols, uns rows);
struct image_io_read_data_internals rdi;
uns read_flags = io->flags;
if ((read_flags & IMAGE_IO_USE_BACKGROUND) && !(read_flags & IMAGE_ALPHA))
- read_flags |= IMAGE_ALPHA;
+ read_flags = (read_flags | IMAGE_ALPHA) & IMAGE_CHANNELS_FORMAT;
if (unlikely(!image_io_read_data_prepare(&rdi, io, rd->image->columns, rd->image->rows, read_flags)))
{
libmagick_destroy_read_data(rd);
if (io->flags & IMAGE_IO_USE_BACKGROUND)
{
png_set_add_alpha(rd->png_ptr, 255, PNG_FILLER_AFTER);
- read_flags |= IMAGE_ALPHA;
+ read_flags = (read_flags | IMAGE_ALPHA) & IMAGE_CHANNELS_FORMAT;
}
else if ((io->flags & IMAGE_PIXEL_FORMAT) == (COLOR_SPACE_RGB | IMAGE_PIXELS_ALIGNED))
png_set_add_alpha(rd->png_ptr, 255, PNG_FILLER_AFTER);
if (!(io->flags & IMAGE_ALPHA))
{
if (io->flags & IMAGE_IO_USE_BACKGROUND)
- read_flags |= IMAGE_ALPHA;
+ read_flags = (read_flags | IMAGE_ALPHA) & IMAGE_CHANNELS_FORMAT;
else
png_set_strip_alpha(rd->png_ptr);
}
png_set_rgb_to_gray_fixed(rd->png_ptr, 1, 21267, 71514);
if (!(io->flags & IMAGE_ALPHA))
if (io->flags & IMAGE_IO_USE_BACKGROUND)
- read_flags |= IMAGE_ALPHA;
+ read_flags = (read_flags | IMAGE_ALPHA) & IMAGE_CHANNELS_FORMAT;
else if ((io->flags & IMAGE_PIXEL_FORMAT) != (COLOR_SPACE_RGB | IMAGE_PIXELS_ALIGNED))
png_set_strip_alpha(rd->png_ptr);
break;
{
if (!ref)
io->flags |= IMAGE_IO_NEED_DESTROY;
+ else
+ io->flags &= ~IMAGE_IO_NEED_DESTROY;
return io->image;
}
else
{
DBG("image_io_read_data_prepare()");
if (rdi->need_transformations = io->cols != cols || io->rows != rows ||
- ((io->flags ^ flags) & (IMAGE_IO_IMAGE_FLAGS & ~IMAGE_NEED_DESTROY)))
+ ((io->flags ^ flags) & IMAGE_NEW_FLAGS))
return rdi->image = image_new(io->thread, cols, rows, flags & IMAGE_IO_IMAGE_FLAGS, NULL);
else
return rdi->image = image_new(io->thread, io->cols, io->rows, io->flags & IMAGE_IO_IMAGE_FLAGS, io->pool);
if (io->cols != rdi->image->cols || io->rows != rdi->image->rows)
{
DBG("Scaling image");
- rdi->need_transformations = ((io->flags ^ rdi->image->flags) & (IMAGE_IO_IMAGE_FLAGS & ~IMAGE_NEED_DESTROY));
+ rdi->need_transformations = ((io->flags ^ rdi->image->flags) & IMAGE_NEW_FLAGS);
struct image *img = image_new(io->thread, io->cols, io->rows, rdi->image->flags, rdi->need_transformations ? NULL : io->pool);
if (unlikely(!img))
{
if ((io->flags ^ rdi->image->flags) & IMAGE_ALPHA)
{
DBG("Aplying background");
- rdi->need_transformations = 0;
- struct image *img = image_new(io->thread, io->cols, io->rows, io->flags, rdi->need_transformations ? NULL : io->pool);
+ uns flags = rdi->image->flags & ~IMAGE_ALPHA;
+ rdi->need_transformations = (flags & io->flags) & IMAGE_NEW_FLAGS;
+ struct image *img = image_new(io->thread, io->cols, io->rows, flags, rdi->need_transformations ? NULL : io->pool);
if (unlikely(!img))
{
image_destroy(rdi->image);