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