blob: 5b73163b2d445081144489d9f617555c2d2fb669 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27/*
28 * FUNCTION
29 * mlib_ImageCreateStruct - create image data structure
30 * mlib_ImageCreate - create image data structure and allocate
31 * memory for image data
32 * mlib_ImageDelete - delete image
33 * mlib_ImageCreateSubimage - create sub-image
34 *
35 * mlib_ImageCreateRowTable - create row starts pointer table
36 * mlib_ImageDeleteRowTable - delete row starts pointer table
37 *
38 * mlib_ImageSetPaddings - set paddings for clipping box borders
39 *
40 * mlib_ImageSetFormat - set image format
41 *
42 * SYNOPSIS
43 * mlib_image *mlib_ImageCreateStruct(mlib_type type,
44 * mlib_s32 channels,
45 * mlib_s32 width,
46 * mlib_s32 height,
47 * mlib_s32 stride,
48 * const void *data)
49 *
50 * mlib_image *mlib_ImageCreate(mlib_type type,
51 * mlib_s32 channels,
52 * mlib_s32 width,
53 * mlib_s32 height)
54 *
55 * void mlib_ImageDelete(mlib_image *img)
56 *
57 * mlib_image *mlib_ImageCreateSubimage(mlib_image *img,
58 * mlib_s32 x,
59 * mlib_s32 y,
60 * mlib_s32 w,
61 * mlib_s32 h)
62 *
63 * void *mlib_ImageCreateRowTable(mlib_image *img)
64 *
65 * void mlib_ImageDeleteRowTable(mlib_image *img)
66 *
67 * mlib_status mlib_ImageSetPaddings(mlib_image *img,
68 * mlib_u8 left,
69 * mlib_u8 top,
70 * mlib_u8 right,
71 * mlib_u8 bottom)
72 *
73 * mlib_status mlib_ImageSetFormat(mlib_image *img,
74 * mlib_format format)
75 * ARGUMENTS
76 * img pointer to image data structure
77 * type image data type, one of MLIB_BIT, MLIB_BYTE, MLIB_SHORT,
78 * MLIB_USHORT, MLIB_INT, MLIB_FLOAT or MLIB_DOUBLE
79 * channels number of image channels
80 * width image width in pixels
81 * height image height in pixels
82 * stride linebytes( bytes to next row) of the image
83 * data pointer to image data allocated by user
84 * x x coordinate of the left border in the source image
85 * y y coordinate of the top border in the source image
86 * w width of the sub-image
87 * h height of the sub-image
88 * left clipping box left padding
89 * top clipping box top padding
90 * right clipping box right padding
91 * bottom clipping box bottom padding
92 * format image format
93 *
94 * DESCRIPTION
95 * mlib_ImageCreateStruct() creates a mediaLib image data structure
96 * using parameter supplied by user.
97 *
98 * mlib_ImageCreate() creates a mediaLib image data structure and
99 * allocates memory space for image data.
100 *
101 * mlib_ImageDelete() deletes the mediaLib image data structure
102 * and frees the memory space of the image data if it is allocated
103 * through mlib_ImageCreate().
104 *
105 * mlib_ImageCreateSubimage() creates a mediaLib image structure
106 * for a sub-image based on a source image.
107 *
108 * mlib_ImageCreateRowTable() creates row starts pointer table and
109 * puts it into mlib_image->state field.
110 *
111 * mlib_ImageDeleteRowTable() deletes row starts pointer table from
112 * image and puts NULL into mlib_image->state field.
113 *
114 * mlib_ImageSetPaddings() sets new values for the clipping box paddings
115 *
116 * mlib_ImageSetFormat() sets new value for the image format
117 */
118
119#include <stdlib.h>
120#include "mlib_image.h"
121#include "mlib_ImageRowTable.h"
122#include "mlib_ImageCreate.h"
123
124/***************************************************************/
125mlib_image* mlib_ImageSet(mlib_image *image,
126 mlib_type type,
127 mlib_s32 channels,
128 mlib_s32 width,
129 mlib_s32 height,
130 mlib_s32 stride,
131 const void *data)
132{
133 mlib_s32 wb; /* width in bytes */
134 mlib_s32 mask; /* mask for check of stride */
135
136 if (image == NULL) return NULL;
137
138/* for some ugly functions calling with incorrect parameters */
139 image -> type = type;
140 image -> channels = channels;
141 image -> width = width;
142 image -> height = height;
143 image -> stride = stride;
144 image -> data = (void *)data;
145 image -> state = NULL;
146 image -> format = MLIB_FORMAT_UNKNOWN;
147
148 image -> paddings[0] = 0;
149 image -> paddings[1] = 0;
150 image -> paddings[2] = 0;
151 image -> paddings[3] = 0;
152
153 image -> bitoffset = 0;
154
155 if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {
156 return NULL;
157 }
158
159/* Check if stride == width
160 * If it is then image can be treated as a 1-D vector
161 */
162 switch (type) {
163 case MLIB_DOUBLE:
164 wb = width * channels * 8;
165 mask = 7;
166 break;
167 case MLIB_FLOAT:
168 case MLIB_INT:
169 wb = width * channels * 4;
170 mask = 3;
171 break;
172 case MLIB_USHORT:
173 case MLIB_SHORT:
174 wb = width * channels * 2;
175 mask = 1;
176 break;
177 case MLIB_BYTE:
178 wb = width * channels;
179 mask = 0;
180 break;
181 case MLIB_BIT:
182 wb = (width * channels + 7) / 8;
183 mask = 0;
184 break;
185 default:
186 return NULL;
187 }
188
189 if (stride & mask) {
190 return NULL;
191 }
192
193 image -> flags = ((width & 0xf) << 8); /* set width field */
194 image -> flags |= ((stride & 0xf) << 16); /* set stride field */
195 image -> flags |= ((height & 0xf) << 12); /* set height field */
196 image -> flags |= (mlib_addr)data & 0xff;
197 image -> flags |= MLIB_IMAGE_USERALLOCATED; /* user allocated data */
198
199 if ((stride != wb) ||
200 ((type == MLIB_BIT) && (stride * 8 != width * channels))) {
201 image -> flags |= MLIB_IMAGE_ONEDVECTOR;
202 }
203
204 image -> flags &= MLIB_IMAGE_ATTRIBUTESET;
205
206 return image;
207}
208
209/***************************************************************/
210mlib_image *mlib_ImageCreateStruct(mlib_type type,
211 mlib_s32 channels,
212 mlib_s32 width,
213 mlib_s32 height,
214 mlib_s32 stride,
215 const void *data)
216{
217 mlib_image *image;
218 if (stride <= 0) {
219 return NULL;
220 }
221
222 image = (mlib_image *)mlib_malloc(sizeof(mlib_image));
223 if (image == NULL) {
224 return NULL;
225 }
226
227 if (mlib_ImageSet(image, type, channels, width, height, stride, data) == NULL) {
228 mlib_free(image);
229 image = NULL;
230 }
231
232 return image;
233}
234
235/***************************************************************/
236mlib_image *mlib_ImageCreate(mlib_type type,
237 mlib_s32 channels,
238 mlib_s32 width,
239 mlib_s32 height)
240{
241 mlib_image *image;
242 mlib_s32 wb; /* width in bytes */
243 void *data;
244
245/* sanity check */
246 if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {
247 return NULL;
248 };
249
250 switch (type) {
251 case MLIB_DOUBLE:
252 wb = width * channels * 8;
253 break;
254 case MLIB_FLOAT:
255 case MLIB_INT:
256 wb = width * channels * 4;
257 break;
258 case MLIB_USHORT:
259 case MLIB_SHORT:
260 wb = width * channels * 2;
261 break;
262 case MLIB_BYTE:
263 wb = width * channels;
264 break;
265 case MLIB_BIT:
266 wb = (width * channels + 7) / 8;
267 break;
268 default:
269 return NULL;
270 }
271
272 data = mlib_malloc(wb * height);
273 if (data == NULL) {
274 return NULL;
275 }
276
277 image = (mlib_image *)mlib_malloc(sizeof(mlib_image));
278 if (image == NULL) {
279 mlib_free(data);
280 return NULL;
281 };
282
283 image -> type = type;
284 image -> channels = channels;
285 image -> width = width;
286 image -> height = height;
287 image -> stride = wb;
288 image -> data = data;
289 image -> flags = ((width & 0xf) << 8); /* set width field */
290 image -> flags |= ((height & 0xf) << 12); /* set height field */
291 image -> flags |= ((wb & 0xf) << 16); /* set stride field */
292 image -> flags |= (mlib_addr)data & 0xff;
293 image -> format = MLIB_FORMAT_UNKNOWN;
294
295 image -> paddings[0] = 0;
296 image -> paddings[1] = 0;
297 image -> paddings[2] = 0;
298 image -> paddings[3] = 0;
299
300 image -> bitoffset = 0;
301
302 if ((type == MLIB_BIT) && (wb * 8 != width * channels)) {
303 image -> flags |= MLIB_IMAGE_ONEDVECTOR; /* not 1-d vector */
304 }
305
306 image -> flags &= MLIB_IMAGE_ATTRIBUTESET;
307 image -> state = NULL;
308
309 return image;
310}
311
312/***************************************************************/
313void mlib_ImageDelete(mlib_image *img)
314{
315 if (img == NULL) return;
316 if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) {
317 mlib_free(img -> data);
318 }
319
320 mlib_ImageDeleteRowTable(img);
321 mlib_free(img);
322}
323
324/***************************************************************/
325mlib_image *mlib_ImageCreateSubimage(mlib_image *img,
326 mlib_s32 x,
327 mlib_s32 y,
328 mlib_s32 w,
329 mlib_s32 h)
330{
331 mlib_image *subimage;
332 mlib_type type;
333 mlib_s32 channels;
334 mlib_s32 width; /* for parent image */
335 mlib_s32 height; /* for parent image */
336 mlib_s32 stride;
337 mlib_s32 bitoffset;
338 void *data;
339
340/* sanity check */
341 if (w <= 0 || h <= 0 || img == NULL) return NULL;
342
343 type = img -> type;
344 channels = img -> channels;
345 width = img -> width;
346 height = img -> height;
347 stride = img -> stride;
348
349/* clip the sub-image with respect to the parent image */
350 if (((x + w) <= 0) || ((y + h) <= 0) ||
351 (x >= width) || (y >= height)) {
352 return NULL;
353 }
354 else {
355 if (x < 0) {
356 w += x; /* x is negative */
357 x = 0;
358 }
359
360 if (y < 0) {
361 h += y; /* y is negative */
362 y = 0;
363 }
364
365 if ((x + w) > width) {
366 w = width - x;
367 }
368
369 if ((y + h) > height) {
370 h = height - y;
371 }
372 }
373
374/* compute sub-image origin */
375 data = (mlib_u8 *)(img -> data) + y * stride;
376
377 switch (type) {
378 case MLIB_DOUBLE:
379 data = (mlib_u8 *)data + x * channels * 8;
380 break;
381 case MLIB_FLOAT:
382 case MLIB_INT:
383 data = (mlib_u8 *)data + x * channels * 4;
384 break;
385 case MLIB_USHORT:
386 case MLIB_SHORT:
387 data = (mlib_u8 *)data + x * channels * 2;
388 break;
389 case MLIB_BYTE:
390 data = (mlib_u8 *)data + x * channels;
391 break;
392 case MLIB_BIT:
393 bitoffset = img -> bitoffset;
394 data = (mlib_u8 *)data + (x * channels + bitoffset) / 8;
395 bitoffset = (x * channels + bitoffset) & 7;
396 break;
397 default:
398 return NULL;
399 }
400
401 subimage = mlib_ImageCreateStruct(type,
402 channels,
403 w,
404 h,
405 stride,
406 data);
407
408 if (subimage != NULL && type == MLIB_BIT)
409 subimage -> bitoffset = bitoffset;
410
411 return subimage;
412}
413
414/***************************************************************/
415mlib_image *mlib_ImageSetSubimage(mlib_image *dst,
416 const mlib_image *src,
417 mlib_s32 x,
418 mlib_s32 y,
419 mlib_s32 w,
420 mlib_s32 h)
421{
422 mlib_type type = src -> type;
423 mlib_s32 channels = src -> channels;
424 mlib_s32 stride = src -> stride;
425 mlib_u8 *data = src -> data;
426 mlib_s32 bitoffset;
427
428 data += y * stride;
429
430 switch (type) {
431 case MLIB_DOUBLE:
432 data += channels * x * 8;
433 break;
434 case MLIB_FLOAT:
435 case MLIB_INT:
436 data += channels * x * 4;
437 break;
438 case MLIB_USHORT:
439 case MLIB_SHORT:
440 data += channels * x * 2;
441 break;
442 case MLIB_BYTE:
443 data += channels * x;
444 break;
445 case MLIB_BIT:
446 bitoffset = src -> bitoffset + channels * x;
447 data += (bitoffset >= 0) ? bitoffset/8 : (bitoffset - 7)/8; /* with rounding toward -Inf */
448 bitoffset &= 7;
449 break;
450 default:
451 return NULL;
452 }
453
454 if (h > 0) {
455 dst = mlib_ImageSet(dst, type, channels, w, h, stride, data);
456 } else {
457 h = - h;
458 dst = mlib_ImageSet(dst, type, channels, w, h, - stride, data + (h - 1)*stride);
459 }
460
461 if (dst != NULL && type == MLIB_BIT) {
462 dst -> bitoffset = bitoffset;
463 }
464
465 return dst;
466}
467
468/***************************************************************/
469void *mlib_ImageCreateRowTable(mlib_image *img)
470{
471 mlib_u8 **rtable, *tline;
472 mlib_s32 i, im_height, im_stride;
473
474 if (img == NULL) return NULL;
475 if (img -> state) return img -> state;
476
477 im_height = mlib_ImageGetHeight(img);
478 im_stride = mlib_ImageGetStride(img);
479 tline = mlib_ImageGetData(img);
480 rtable = mlib_malloc((3 + im_height)*sizeof(mlib_u8 *));
481
482 if (rtable == NULL || tline == NULL) return NULL;
483
484 rtable[0] = 0;
485 rtable[1] = (mlib_u8*)((void **)rtable + 1);
486 rtable[2 + im_height] = (mlib_u8*)((void **)rtable + 1);
487 for (i = 0; i < im_height; i++) {
488 rtable[i+2] = tline;
489 tline += im_stride;
490 }
491
492 img -> state = ((void **)rtable + 2);
493 return img -> state;
494}
495
496/***************************************************************/
497void mlib_ImageDeleteRowTable(mlib_image *img)
498{
499 void **state;
500
501 if (img == NULL) return;
502
503 state = img -> state;
504 if (!state) return;
505
506 mlib_free(state - 2);
507 img -> state = 0;
508}
509
510/***************************************************************/
511mlib_status mlib_ImageSetPaddings(mlib_image *img,
512 mlib_u8 left,
513 mlib_u8 top,
514 mlib_u8 right,
515 mlib_u8 bottom)
516{
517 if (img == NULL) return MLIB_FAILURE;
518
519 if ((left + right) >= img -> width ||
520 (top + bottom) >= img -> height) return MLIB_OUTOFRANGE;
521
522 img -> paddings[0] = left;
523 img -> paddings[1] = top;
524 img -> paddings[2] = right;
525 img -> paddings[3] = bottom;
526
527 return MLIB_SUCCESS;
528}
529
530/***************************************************************/
531mlib_status mlib_ImageSetFormat(mlib_image *img,
532 mlib_format format)
533{
534 if (img == NULL) return MLIB_FAILURE;
535
536 img -> format = format;
537
538 return MLIB_SUCCESS;
539}
540
541/***************************************************************/