1 /* 2 * Copyright (c) 1997, 2018, 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 JNIEXPORT 231 mlib_image* mlib_ImageCreateStruct(mlib_type type, 232 mlib_s32 channels, 233 mlib_s32 width, 234 mlib_s32 height, 235 mlib_s32 stride, 236 const void *data) 237 { 238 mlib_image *image; 239 if (stride <= 0) { 240 return NULL; 241 } 242 243 image = (mlib_image *)mlib_malloc(sizeof(mlib_image)); 244 if (image == NULL) { 245 return NULL; 246 } 247 248 if (mlib_ImageSet(image, type, channels, width, height, stride, data) == NULL) { 249 mlib_free(image); 250 image = NULL; 251 } 252 253 return image; 254 } 255 256 /***************************************************************/ 257 JNIEXPORT 258 mlib_image* mlib_ImageCreate(mlib_type type, 259 mlib_s32 channels, 260 mlib_s32 width, 261 mlib_s32 height) 262 { 263 mlib_image *image; 264 mlib_s32 wb; /* width in bytes */ 265 void *data; 266 267 /* sanity check */ 268 if (width <= 0 || height <= 0 || channels < 1 || channels > 4) { 269 return NULL; 270 }; 271 272 if (!SAFE_TO_MULT(width, channels)) { 273 return NULL; 274 } 275 276 wb = width * channels; 277 278 switch (type) { 279 case MLIB_DOUBLE: 280 if (!SAFE_TO_MULT(wb, 8)) { 281 return NULL; 282 } 283 wb *= 8; 284 break; 285 case MLIB_FLOAT: 286 case MLIB_INT: 287 if (!SAFE_TO_MULT(wb, 4)) { 288 return NULL; 289 } 290 wb *= 4; 291 break; 292 case MLIB_USHORT: 293 case MLIB_SHORT: 294 if (!SAFE_TO_MULT(wb, 2)) { 295 return NULL; 296 } 297 wb *= 2; 298 break; 299 case MLIB_BYTE: 300 // wb is ready 301 break; 302 case MLIB_BIT: 303 if (!SAFE_TO_ADD(7, wb)) { 304 return NULL; 305 } 306 wb = (wb + 7) / 8; 307 break; 308 default: 309 return NULL; 310 } 311 312 if (!SAFE_TO_MULT(wb, height)) { 313 return NULL; 314 } 315 316 data = mlib_malloc(wb * height); 317 if (data == NULL) { 318 return NULL; 319 } 320 321 image = (mlib_image *)mlib_malloc(sizeof(mlib_image)); 322 if (image == NULL) { 323 mlib_free(data); 324 return NULL; 325 }; 326 327 image -> type = type; 328 image -> channels = channels; 329 image -> width = width; 330 image -> height = height; 331 image -> stride = wb; 332 image -> data = data; 333 image -> flags = ((width & 0xf) << 8); /* set width field */ 334 image -> flags |= ((height & 0xf) << 12); /* set height field */ 335 image -> flags |= ((wb & 0xf) << 16); /* set stride field */ 336 image -> flags |= (mlib_addr)data & 0xff; 337 image -> format = MLIB_FORMAT_UNKNOWN; 338 339 image -> paddings[0] = 0; 340 image -> paddings[1] = 0; 341 image -> paddings[2] = 0; 342 image -> paddings[3] = 0; 343 344 image -> bitoffset = 0; 345 346 if ((type == MLIB_BIT) && (wb * 8 != width * channels)) { 347 image -> flags |= MLIB_IMAGE_ONEDVECTOR; /* not 1-d vector */ 348 } 349 350 image -> flags &= MLIB_IMAGE_ATTRIBUTESET; 351 image -> state = NULL; 352 353 return image; 354 } 355 356 /***************************************************************/ 357 JNIEXPORT 358 void mlib_ImageDelete(mlib_image *img) 359 { 360 if (img == NULL) return; 361 if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) { 362 mlib_free(img -> data); 363 } 364 365 mlib_ImageDeleteRowTable(img); 366 mlib_free(img); 367 } 368 369 /***************************************************************/ 370 mlib_image *mlib_ImageCreateSubimage(mlib_image *img, 371 mlib_s32 x, 372 mlib_s32 y, 373 mlib_s32 w, 374 mlib_s32 h) 375 { 376 mlib_image *subimage; 377 mlib_type type; 378 mlib_s32 channels; 379 mlib_s32 width; /* for parent image */ 380 mlib_s32 height; /* for parent image */ 381 mlib_s32 stride; 382 mlib_s32 bitoffset = 0; 383 void *data; 384 385 /* sanity check */ 386 if (w <= 0 || h <= 0 || img == NULL) return NULL; 387 388 type = img -> type; 389 channels = img -> channels; 390 width = img -> width; 391 height = img -> height; 392 stride = img -> stride; 393 394 /* clip the sub-image with respect to the parent image */ 395 if (((x + w) <= 0) || ((y + h) <= 0) || 396 (x >= width) || (y >= height)) { 397 return NULL; 398 } 399 else { 400 if (x < 0) { 401 w += x; /* x is negative */ 402 x = 0; 403 } 404 405 if (y < 0) { 406 h += y; /* y is negative */ 407 y = 0; 408 } 409 410 if ((x + w) > width) { 411 w = width - x; 412 } 413 414 if ((y + h) > height) { 415 h = height - y; 416 } 417 } 418 419 /* compute sub-image origin */ 420 data = (mlib_u8 *)(img -> data) + y * stride; 421 422 switch (type) { 423 case MLIB_DOUBLE: 424 data = (mlib_u8 *)data + x * channels * 8; 425 break; 426 case MLIB_FLOAT: 427 case MLIB_INT: 428 data = (mlib_u8 *)data + x * channels * 4; 429 break; 430 case MLIB_USHORT: 431 case MLIB_SHORT: 432 data = (mlib_u8 *)data + x * channels * 2; 433 break; 434 case MLIB_BYTE: 435 data = (mlib_u8 *)data + x * channels; 436 break; 437 case MLIB_BIT: 438 bitoffset = img -> bitoffset; 439 data = (mlib_u8 *)data + (x * channels + bitoffset) / 8; 440 bitoffset = (x * channels + bitoffset) & 7; 441 break; 442 default: 443 return NULL; 444 } 445 446 subimage = mlib_ImageCreateStruct(type, 447 channels, 448 w, 449 h, 450 stride, 451 data); 452 453 if (subimage != NULL && type == MLIB_BIT) 454 subimage -> bitoffset = bitoffset; 455 456 return subimage; 457 } 458 459 /***************************************************************/ 460 mlib_image *mlib_ImageSetSubimage(mlib_image *dst, 461 const mlib_image *src, 462 mlib_s32 x, 463 mlib_s32 y, 464 mlib_s32 w, 465 mlib_s32 h) 466 { 467 mlib_type type = src -> type; 468 mlib_s32 channels = src -> channels; 469 mlib_s32 stride = src -> stride; 470 mlib_u8 *data = src -> data; 471 mlib_s32 bitoffset = 0; 472 473 data += y * stride; 474 475 switch (type) { 476 case MLIB_DOUBLE: 477 data += channels * x * 8; 478 break; 479 case MLIB_FLOAT: 480 case MLIB_INT: 481 data += channels * x * 4; 482 break; 483 case MLIB_USHORT: 484 case MLIB_SHORT: 485 data += channels * x * 2; 486 break; 487 case MLIB_BYTE: 488 data += channels * x; 489 break; 490 case MLIB_BIT: 491 bitoffset = src -> bitoffset + channels * x; 492 data += (bitoffset >= 0) ? bitoffset/8 : (bitoffset - 7)/8; /* with rounding toward -Inf */ 493 bitoffset &= 7; 494 break; 495 default: 496 return NULL; 497 } 498 499 if (h > 0) { 500 dst = mlib_ImageSet(dst, type, channels, w, h, stride, data); 501 } else { 502 h = - h; 503 dst = mlib_ImageSet(dst, type, channels, w, h, - stride, data + (h - 1)*stride); 504 } 505 506 if (dst != NULL && type == MLIB_BIT) { 507 dst -> bitoffset = bitoffset; 508 } 509 510 return dst; 511 } 512 513 /***************************************************************/ 514 void *mlib_ImageCreateRowTable(mlib_image *img) 515 { 516 mlib_u8 **rtable, *tline; 517 mlib_s32 i, im_height, im_stride; 518 519 if (img == NULL) return NULL; 520 if (img -> state) return img -> state; 521 522 im_height = mlib_ImageGetHeight(img); 523 im_stride = mlib_ImageGetStride(img); 524 tline = mlib_ImageGetData(img); 525 if (tline == NULL) return NULL; 526 rtable = mlib_malloc((3 + im_height)*sizeof(mlib_u8 *)); 527 if (rtable == NULL) return NULL; 528 529 rtable[0] = 0; 530 rtable[1] = (mlib_u8*)((void **)rtable + 1); 531 rtable[2 + im_height] = (mlib_u8*)((void **)rtable + 1); 532 for (i = 0; i < im_height; i++) { 533 rtable[i+2] = tline; 534 tline += im_stride; 535 } 536 537 img -> state = ((void **)rtable + 2); 538 return img -> state; 539 } 540 541 /***************************************************************/ 542 void mlib_ImageDeleteRowTable(mlib_image *img) 543 { 544 void **state; 545 546 if (img == NULL) return; 547 548 state = img -> state; 549 if (!state) return; 550 551 mlib_free(state - 2); 552 img -> state = 0; 553 } 554 555 /***************************************************************/ 556 mlib_status mlib_ImageSetPaddings(mlib_image *img, 557 mlib_u8 left, 558 mlib_u8 top, 559 mlib_u8 right, 560 mlib_u8 bottom) 561 { 562 if (img == NULL) return MLIB_FAILURE; 563 564 if ((left + right) >= img -> width || 565 (top + bottom) >= img -> height) return MLIB_OUTOFRANGE; 566 567 img -> paddings[0] = left; 568 img -> paddings[1] = top; 569 img -> paddings[2] = right; 570 img -> paddings[3] = bottom; 571 572 return MLIB_SUCCESS; 573 } 574 575 /***************************************************************/ 576 mlib_status mlib_ImageSetFormat(mlib_image *img, 577 mlib_format format) 578 { 579 if (img == NULL) return MLIB_FAILURE; 580 581 img -> format = format; 582 583 return MLIB_SUCCESS; 584 } 585 586 /***************************************************************/