2 * Image Library -- Basic image manipulation
4 * (c) 2006 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
13 #include "lib/mempool.h"
14 #include "images/images.h"
17 #define MAX_IMAGE_BYTES (1 << 30)
20 image_thread_init(struct image_thread *it)
22 DBG("image_thread_init()");
23 bzero(it, sizeof(*it));
24 it->pool = mp_new(1024);
28 image_thread_cleanup(struct image_thread *it)
30 DBG("image_thread_cleanup()");
35 image_thread_err_format(struct image_thread *it, uns code, char *msg, ...)
40 it->err_msg = mp_vprintf(it->pool, msg, args);
45 image_new(struct image_thread *it, uns cols, uns rows, uns flags, struct mempool *pool)
47 DBG("image_new(cols=%u rows=%u flags=0x%x pool=%p)", cols, rows, flags, pool);
48 if (cols > IMAGE_MAX_SIZE || rows > IMAGE_MAX_SIZE)
50 image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image dimension(s) too large");
54 uns pixel_size, row_size, image_size, align;
55 switch (flags & IMAGE_COLOR_SPACE)
57 case COLOR_SPACE_GRAYSCALE:
66 if (flags & IMAGE_ALPHA)
73 flags |= IMAGE_PIXELS_ALIGNED;
76 if (flags & IMAGE_PIXELS_ALIGNED)
82 if (flags & IMAGE_SSE_ALIGNED)
83 align = IMAGE_SSE_ALIGN_SIZE;
84 else if (flags & IMAGE_PIXELS_ALIGNED)
88 row_size = cols * pixel_size;
89 row_size = ALIGN(row_size, align);
90 u64 image_size_64 = (u64)row_size * rows;
91 u64 bytes_64 = image_size_64 + (sizeof(struct image) + IMAGE_SSE_ALIGN_SIZE - 1 + sizeof(uns));
92 if (bytes_64 > MAX_IMAGE_BYTES)
94 image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Image does not fit in memory");
97 if (!(image_size = image_size_64))
99 image_thread_err(it, IMAGE_ERR_INVALID_DIMENSIONS, "Zero dimension(s)");
102 img = pool ? mp_alloc(pool, (uns)bytes_64) : xmalloc((uns)bytes_64);
103 bzero(img, sizeof(struct image));
104 byte *p = (byte *)img + sizeof(struct image);
105 img->pixels = ALIGN_PTR(p, IMAGE_SSE_ALIGN_SIZE);
107 img->pixel_size = pixel_size;
110 img->row_size = row_size;
111 img->image_size = image_size;
112 DBG("img=%p flags=0x%x pixel_size=%u row_size=%u image_size=%u pixels=%p",
113 img, img->flags, img->pixel_size, img->row_size, img->image_size, img->pixels);
118 image_clone(struct image_thread *it, struct image *src, uns flags, struct mempool *pool)
120 DBG("image_clone(src=%p flags=0x%x pool=%p)", src, src->flags, pool);
122 flags &= ~IMAGE_CHANNELS_FORMAT;
123 flags |= src->flags & IMAGE_CHANNELS_FORMAT;
124 if (!(img = image_new(it, src->cols, src->rows, flags, pool)))
128 if (src->pixel_size != img->pixel_size)
130 struct image *sec_img = src;
131 # define IMAGE_WALK_INLINE
132 # define IMAGE_WALK_DOUBLE
133 # define IMAGE_WALK_DO_STEP do{ *(u32 *)pos = *(u32 *)sec_pos; }while(0)
134 # include "images/image-walk.h"
136 else if (src->row_size != img->row_size)
138 byte *s = src->pixels;
139 byte *d = img->pixels;
140 uns bytes = src->cols * img->pixel_size;
141 for (uns row = src->rows; row--; )
149 memcpy(img->pixels, src->pixels, img->image_size);
155 image_destroy(struct image_thread *it UNUSED, struct image *img)
157 DBG("image_destroy(img=%p)", img);
162 image_clear(struct image_thread *it UNUSED, struct image *img)
164 DBG("image_clear(img=%p)", img);
166 bzero(img->pixels, img->image_size);
170 color_space_to_name(enum color_space cs)
172 return image_channels_format_to_name(cs);
176 image_channels_format_to_name(uns format)
180 case COLOR_SPACE_GRAYSCALE:
182 case COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA:
184 case COLOR_SPACE_RGB:
186 case COLOR_SPACE_RGB | IMAGE_ALPHA:
194 image_name_to_channels_format(byte *name)
196 if (!strcasecmp(name, "gray"))
197 return COLOR_SPACE_GRAYSCALE;
198 if (!strcasecmp(name, "grayscale"))
199 return COLOR_SPACE_GRAYSCALE;
200 if (!strcasecmp(name, "grayalpha"))
201 return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
202 if (!strcasecmp(name, "grayscalealpha"))
203 return COLOR_SPACE_GRAYSCALE | IMAGE_ALPHA;
204 if (!strcasecmp(name, "rgb"))
205 return COLOR_SPACE_RGB;
206 if (!strcasecmp(name, "rgbalpha"))
207 return COLOR_SPACE_RGB + IMAGE_ALPHA;
208 if (!strcasecmp(name, "rgba"))
209 return COLOR_SPACE_RGB + IMAGE_ALPHA;