1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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 #include "safe_math.h" 124 125 /***************************************************************/ 126 mlib_image* mlib_ImageSet(mlib_image *image, 127 mlib_type type, 128 mlib_s32 channels, 129 mlib_s32 width, 130 mlib_s32 height, 131 mlib_s32 stride, 132 const void *data) 133 { 134 mlib_s32 wb; /* width in bytes */ 135 mlib_s32 mask; /* mask for check of stride */ 136 137 if (image == NULL) return NULL; 138 139 /* for some ugly functions calling with incorrect parameters */ 140 image -> type = type; 141 image -> channels = channels; 142 image -> width = width; 143 image -> height = height; 144 image -> stride = stride; 145 image -> data = (void *)data; 146 image -> state = NULL; 147 image -> format = MLIB_FORMAT_UNKNOWN; 148 149 image -> paddings[0] = 0; 150 image -> paddings[1] = 0; 151 image -> paddings[2] = 0; 152 image -> paddings[3] = 0; 153 154 image -> bitoffset = 0; 155 156 if (width <= 0 || height <= 0 || channels < 1 || channels > 4) { 157 return NULL; 158 } 159 160 /* Check if stride == width 161 * If it is then image can be treated as a 1-D vector 162 */ 163 164 if (!SAFE_TO_MULT(width, channels)) { 165 return NULL; 166 } 167 168 wb = width * channels; 169 170 switch (type) { 171 case MLIB_DOUBLE: 172 if (!SAFE_TO_MULT(wb, 8)) { 173 return NULL; 174 } 175 wb *= 8; 176 mask = 7; 177 break; 178 case MLIB_FLOAT: 179 case MLIB_INT: 180 if (!SAFE_TO_MULT(wb, 4)) { 181 return NULL; 182 } 183 wb *= 4; 184 mask = 3; 185 break; 186 case MLIB_USHORT: 187 case MLIB_SHORT: 188 if (!SAFE_TO_MULT(wb, 2)) { 189 return NULL; 190 } 191 wb *= 2; 192 mask = 1; 193 break; 194 case MLIB_BYTE: 195 // wb is ready 196 mask = 0; 197 break; 198 case MLIB_BIT: 199 if (!SAFE_TO_ADD(7, wb)) { 200 return NULL; 201 } 202 wb = (wb + 7) / 8; 203 mask = 0; 204 break; 205 default: 206 return NULL; 207 } 208 209 if (stride & mask) { 210 return NULL; 211 } 212 213 image -> flags = ((width & 0xf) << 8); /* set width field */ 214 image -> flags |= ((stride & 0xf) << 16); /* set stride field */ 215 image -> flags |= ((height & 0xf) << 12); /* set height field */ 216 image -> flags |= (mlib_addr)data & 0xff; 217 image -> flags |= MLIB_IMAGE_USERALLOCATED; /* user allocated data */ 218 219 if ((stride != wb) || 220 ((type == MLIB_BIT) && (stride * 8 != width * channels))) { 221 image -> flags |= MLIB_IMAGE_ONEDVECTOR; 222 } 223 224 image -> flags &= MLIB_IMAGE_ATTRIBUTESET; 225 226 return image; 227 } 228 229 /***************************************************************/ 230 mlib_image *mlib_ImageCreateStruct(mlib_type type, 231 mlib_s32 channels, 232 mlib_s32 width, 233 mlib_s32 height, 234 mlib_s32 stride, 235 const void *data) 236 { 237 mlib_image *image; 238 if (stride <= 0) { 239 return NULL; 240 } 241 242 image = (mlib_image *)mlib_malloc(sizeof(mlib_image)); 243 if (image == NULL) { 244 return NULL; 245 } 246 247 if (mlib_ImageSet(image, type, channels, width, height, stride, data) == NULL) { 248 mlib_free(image); 249 image = NULL; 250 } 251 252 return image; 253 } 254 255 /***************************************************************/ 256 mlib_image *mlib_ImageCreate(mlib_type type, 257 mlib_s32 channels, 258 mlib_s32 width, 259 mlib_s32 height) 260 { 261 mlib_image *image; 262 mlib_s32 wb; /* width in bytes */ 263 void *data; 264 265 /* sanity check */ 266 if (width <= 0 || height <= 0 || channels < 1 || channels > 4) { 267 return NULL; 268 }; 269 270 if (!SAFE_TO_MULT(width, channels)) { 271 return NULL; 272 } 273 274 wb = width * channels; 275 276 switch (type) { 277 case MLIB_DOUBLE: 278 if (!SAFE_TO_MULT(wb, 8)) { 279 return NULL; 280 } 281 wb *= 8; 282 break; 283 case MLIB_FLOAT: 284 case MLIB_INT: 285 if (!SAFE_TO_MULT(wb, 4)) { 286 return NULL; 287 } 288 wb *= 4; 289 break; 290 case MLIB_USHORT: 291 case MLIB_SHORT: 292 if (!SAFE_TO_MULT(wb, 2)) { 293 return NULL; 294 } 295 wb *= 2; 296 break; 297 case MLIB_BYTE: 298 // wb is ready 299 break; 300 case MLIB_BIT: 301 if (!SAFE_TO_ADD(7, wb)) { 302 return NULL; 303 } 304 wb = (wb + 7) / 8; 305 break; 306 default: 307 return NULL; 308 } 309 310 if (!SAFE_TO_MULT(wb, height)) { 311 return NULL; 312 } 313 314 data = mlib_malloc(wb * height); 315 if (data == NULL) { 316 return NULL; 317 } 318 319 image = (mlib_image *)mlib_malloc(sizeof(mlib_image)); 320 if (image == NULL) { 321 mlib_free(data); 322 return NULL; 323 }; 324 325 image -> type = type; 326 image -> channels = channels; 327 image -> width = width; 328 image -> height = height; 329 image -> stride = wb; 330 image -> data = data; 331 image -> flags = ((width & 0xf) << 8); /* set width field */ 332 image -> flags |= ((height & 0xf) << 12); /* set height field */ 333 image -> flags |= ((wb & 0xf) << 16); /* set stride field */ 334 image -> flags |= (mlib_addr)data & 0xff; 335 image -> format = MLIB_FORMAT_UNKNOWN; 336 337 image -> paddings[0] = 0; 338 image -> paddings[1] = 0; 339 image -> paddings[2] = 0; 340 image -> paddings[3] = 0; 341 342 image -> bitoffset = 0; 343 344 if ((type == MLIB_BIT) && (wb * 8 != width * channels)) { 345 image -> flags |= MLIB_IMAGE_ONEDVECTOR; /* not 1-d vector */ 346 } 347 348 image -> flags &= MLIB_IMAGE_ATTRIBUTESET; 349 image -> state = NULL; 350 351 return image; 352 } 353 354 /***************************************************************/ 355 void mlib_ImageDelete(mlib_image *img) 356 { 357 if (img == NULL) return; 358 if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) { 359 mlib_free(img -> data); 360 } 361 362 mlib_ImageDeleteRowTable(img); 363 mlib_free(img); 364 } 365 366 /***************************************************************/ 367 mlib_image *mlib_ImageCreateSubimage(mlib_image *img, 368 mlib_s32 x, 369 mlib_s32 y, 370 mlib_s32 w, 371 mlib_s32 h) 372 { 373 mlib_image *subimage; 374 mlib_type type; 375 mlib_s32 channels; 376 mlib_s32 width; /* for parent image */ 377 mlib_s32 height; /* for parent image */ 378 mlib_s32 stride; 379 mlib_s32 bitoffset = 0; 380 void *data; 381 382 /* sanity check */ 383 if (w <= 0 || h <= 0 || img == NULL) return NULL; 384 385 type = img -> type; 386 channels = img -> channels; 387 width = img -> width; 388 height = img -> height; 389 stride = img -> stride; 390 391 /* clip the sub-image with respect to the parent image */ 392 if (((x + w) <= 0) || ((y + h) <= 0) || 393 (x >= width) || (y >= height)) { 394 return NULL; 395 } 396 else { 397 if (x < 0) { 398 w += x; /* x is negative */ 399 x = 0; 400 } 401 402 if (y < 0) { 403 h += y; /* y is negative */ 404 y = 0; 405 } 406 407 if ((x + w) > width) { 408 w = width - x; 409 } 410 411 if ((y + h) > height) { 412 h = height - y; 413 } 414 } 415 416 /* compute sub-image origin */ 417 data = (mlib_u8 *)(img -> data) + y * stride; 418 419 switch (type) { 420 case MLIB_DOUBLE: 421 data = (mlib_u8 *)data + x * channels * 8; 422 break; 423 case MLIB_FLOAT: 424 case MLIB_INT: 425 data = (mlib_u8 *)data + x * channels * 4; 426 break; 427 case MLIB_USHORT: 428 case MLIB_SHORT: 429 data = (mlib_u8 *)data + x * channels * 2; 430 break; 431 case MLIB_BYTE: 432 data = (mlib_u8 *)data + x * channels; 433 break; 434 case MLIB_BIT: 435 bitoffset = img -> bitoffset; 436 data = (mlib_u8 *)data + (x * channels + bitoffset) / 8; 437 bitoffset = (x * channels + bitoffset) & 7; 438 break; 439 default: 440 return NULL; 441 } 442 443 subimage = mlib_ImageCreateStruct(type, 444 channels, 445 w, 446 h, 447 stride, 448 data); 449 450 if (subimage != NULL && type == MLIB_BIT) 451 subimage -> bitoffset = bitoffset; 452 453 return subimage; 454 } 455 456 /***************************************************************/ 457 mlib_image *mlib_ImageSetSubimage(mlib_image *dst, 458 const mlib_image *src, 459 mlib_s32 x, 460 mlib_s32 y, 461 mlib_s32 w, 462 mlib_s32 h) 463 { 464 mlib_type type = src -> type; 465 mlib_s32 channels = src -> channels; 466 mlib_s32 stride = src -> stride; 467 mlib_u8 *data = src -> data; 468 mlib_s32 bitoffset = 0; 469 470 data += y * stride; 471 472 switch (type) { 473 case MLIB_DOUBLE: 474 data += channels * x * 8; 475 break; 476 case MLIB_FLOAT: 477 case MLIB_INT: 478 data += channels * x * 4; 479 break; 480 case MLIB_USHORT: 481 case MLIB_SHORT: 482 data += channels * x * 2; 483 break; 484 case MLIB_BYTE: 485 data += channels * x; 486 break; 487 case MLIB_BIT: 488 bitoffset = src -> bitoffset + channels * x; 489 data += (bitoffset >= 0) ? bitoffset/8 : (bitoffset - 7)/8; /* with rounding toward -Inf */ 490 bitoffset &= 7; 491 break; 492 default: 493 return NULL; 494 } 495 496 if (h > 0) { 497 dst = mlib_ImageSet(dst, type, channels, w, h, stride, data); 498 } else { 499 h = - h; 500 dst = mlib_ImageSet(dst, type, channels, w, h, - stride, data + (h - 1)*stride); 501 } 502 503 if (dst != NULL && type == MLIB_BIT) { 504 dst -> bitoffset = bitoffset; 505 } 506 507 return dst; 508 } 509 510 /***************************************************************/ 511 void *mlib_ImageCreateRowTable(mlib_image *img) 512 { 513 mlib_u8 **rtable, *tline; 514 mlib_s32 i, im_height, im_stride; 515 516 if (img == NULL) return NULL; 517 if (img -> state) return img -> state; 518 519 im_height = mlib_ImageGetHeight(img); 520 im_stride = mlib_ImageGetStride(img); 521 tline = mlib_ImageGetData(img); 522 if (tline == NULL) return NULL; 523 rtable = mlib_malloc((3 + im_height)*sizeof(mlib_u8 *)); 524 if (rtable == NULL) return NULL; 525 526 rtable[0] = 0; 527 rtable[1] = (mlib_u8*)((void **)rtable + 1); 528 rtable[2 + im_height] = (mlib_u8*)((void **)rtable + 1); 529 for (i = 0; i < im_height; i++) { 530 rtable[i+2] = tline; 531 tline += im_stride; 532 } 533 534 img -> state = ((void **)rtable + 2); 535 return img -> state; 536 } 537 538 /***************************************************************/ 539 void mlib_ImageDeleteRowTable(mlib_image *img) 540 { 541 void **state; 542 543 if (img == NULL) return; 544 545 state = img -> state; 546 if (!state) return; 547 548 mlib_free(state - 2); 549 img -> state = 0; 550 } 551 552 /***************************************************************/ 553 mlib_status mlib_ImageSetPaddings(mlib_image *img, 554 mlib_u8 left, 555 mlib_u8 top, 556 mlib_u8 right, 557 mlib_u8 bottom) 558 { 559 if (img == NULL) return MLIB_FAILURE; 560 561 if ((left + right) >= img -> width || 562 (top + bottom) >= img -> height) return MLIB_OUTOFRANGE; 563 564 img -> paddings[0] = left; 565 img -> paddings[1] = top; 566 img -> paddings[2] = right; 567 img -> paddings[3] = bottom; 568 569 return MLIB_SUCCESS; 570 } 571 572 /***************************************************************/ 573 mlib_status mlib_ImageSetFormat(mlib_image *img, 574 mlib_format format) 575 { 576 if (img == NULL) return MLIB_FAILURE; 577 578 img -> format = format; 579 580 return MLIB_SUCCESS; 581 } 582 583 /***************************************************************/