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 /***************************************************************/