0N/A/*
2362N/A * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/A/*
0N/A * FUNCTION
0N/A * mlib_ImageCreateStruct - create image data structure
0N/A * mlib_ImageCreate - create image data structure and allocate
0N/A * memory for image data
0N/A * mlib_ImageDelete - delete image
0N/A * mlib_ImageCreateSubimage - create sub-image
0N/A *
0N/A * mlib_ImageCreateRowTable - create row starts pointer table
0N/A * mlib_ImageDeleteRowTable - delete row starts pointer table
0N/A *
0N/A * mlib_ImageSetPaddings - set paddings for clipping box borders
0N/A *
0N/A * mlib_ImageSetFormat - set image format
0N/A *
0N/A * SYNOPSIS
0N/A * mlib_image *mlib_ImageCreateStruct(mlib_type type,
0N/A * mlib_s32 channels,
0N/A * mlib_s32 width,
0N/A * mlib_s32 height,
0N/A * mlib_s32 stride,
0N/A * const void *data)
0N/A *
0N/A * mlib_image *mlib_ImageCreate(mlib_type type,
0N/A * mlib_s32 channels,
0N/A * mlib_s32 width,
0N/A * mlib_s32 height)
0N/A *
0N/A * void mlib_ImageDelete(mlib_image *img)
0N/A *
0N/A * mlib_image *mlib_ImageCreateSubimage(mlib_image *img,
0N/A * mlib_s32 x,
0N/A * mlib_s32 y,
0N/A * mlib_s32 w,
0N/A * mlib_s32 h)
0N/A *
0N/A * void *mlib_ImageCreateRowTable(mlib_image *img)
0N/A *
0N/A * void mlib_ImageDeleteRowTable(mlib_image *img)
0N/A *
0N/A * mlib_status mlib_ImageSetPaddings(mlib_image *img,
0N/A * mlib_u8 left,
0N/A * mlib_u8 top,
0N/A * mlib_u8 right,
0N/A * mlib_u8 bottom)
0N/A *
0N/A * mlib_status mlib_ImageSetFormat(mlib_image *img,
0N/A * mlib_format format)
0N/A * ARGUMENTS
0N/A * img pointer to image data structure
0N/A * type image data type, one of MLIB_BIT, MLIB_BYTE, MLIB_SHORT,
0N/A * MLIB_USHORT, MLIB_INT, MLIB_FLOAT or MLIB_DOUBLE
0N/A * channels number of image channels
0N/A * width image width in pixels
0N/A * height image height in pixels
0N/A * stride linebytes( bytes to next row) of the image
0N/A * data pointer to image data allocated by user
0N/A * x x coordinate of the left border in the source image
0N/A * y y coordinate of the top border in the source image
0N/A * w width of the sub-image
0N/A * h height of the sub-image
0N/A * left clipping box left padding
0N/A * top clipping box top padding
0N/A * right clipping box right padding
0N/A * bottom clipping box bottom padding
0N/A * format image format
0N/A *
0N/A * DESCRIPTION
0N/A * mlib_ImageCreateStruct() creates a mediaLib image data structure
0N/A * using parameter supplied by user.
0N/A *
0N/A * mlib_ImageCreate() creates a mediaLib image data structure and
0N/A * allocates memory space for image data.
0N/A *
0N/A * mlib_ImageDelete() deletes the mediaLib image data structure
0N/A * and frees the memory space of the image data if it is allocated
0N/A * through mlib_ImageCreate().
0N/A *
0N/A * mlib_ImageCreateSubimage() creates a mediaLib image structure
0N/A * for a sub-image based on a source image.
0N/A *
0N/A * mlib_ImageCreateRowTable() creates row starts pointer table and
0N/A * puts it into mlib_image->state field.
0N/A *
0N/A * mlib_ImageDeleteRowTable() deletes row starts pointer table from
0N/A * image and puts NULL into mlib_image->state field.
0N/A *
0N/A * mlib_ImageSetPaddings() sets new values for the clipping box paddings
0N/A *
0N/A * mlib_ImageSetFormat() sets new value for the image format
0N/A */
0N/A
0N/A#include <stdlib.h>
0N/A#include "mlib_image.h"
0N/A#include "mlib_ImageRowTable.h"
0N/A#include "mlib_ImageCreate.h"
5817N/A#include "safe_math.h"
0N/A
0N/A/***************************************************************/
0N/Amlib_image* mlib_ImageSet(mlib_image *image,
0N/A mlib_type type,
0N/A mlib_s32 channels,
0N/A mlib_s32 width,
0N/A mlib_s32 height,
0N/A mlib_s32 stride,
0N/A const void *data)
0N/A{
0N/A mlib_s32 wb; /* width in bytes */
0N/A mlib_s32 mask; /* mask for check of stride */
0N/A
0N/A if (image == NULL) return NULL;
0N/A
0N/A/* for some ugly functions calling with incorrect parameters */
0N/A image -> type = type;
0N/A image -> channels = channels;
0N/A image -> width = width;
0N/A image -> height = height;
0N/A image -> stride = stride;
0N/A image -> data = (void *)data;
0N/A image -> state = NULL;
0N/A image -> format = MLIB_FORMAT_UNKNOWN;
0N/A
0N/A image -> paddings[0] = 0;
0N/A image -> paddings[1] = 0;
0N/A image -> paddings[2] = 0;
0N/A image -> paddings[3] = 0;
0N/A
0N/A image -> bitoffset = 0;
0N/A
0N/A if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {
0N/A return NULL;
0N/A }
0N/A
0N/A/* Check if stride == width
0N/A * If it is then image can be treated as a 1-D vector
0N/A */
6344N/A
6344N/A if (!SAFE_TO_MULT(width, channels)) {
6344N/A return NULL;
6344N/A }
6344N/A
6344N/A wb = width * channels;
6344N/A
0N/A switch (type) {
0N/A case MLIB_DOUBLE:
6344N/A if (!SAFE_TO_MULT(wb, 8)) {
6344N/A return NULL;
6344N/A }
6344N/A wb *= 8;
0N/A mask = 7;
0N/A break;
0N/A case MLIB_FLOAT:
0N/A case MLIB_INT:
6344N/A if (!SAFE_TO_MULT(wb, 4)) {
6344N/A return NULL;
6344N/A }
6344N/A wb *= 4;
0N/A mask = 3;
0N/A break;
0N/A case MLIB_USHORT:
0N/A case MLIB_SHORT:
6344N/A if (!SAFE_TO_MULT(wb, 2)) {
6344N/A return NULL;
6344N/A }
6344N/A wb *= 2;
0N/A mask = 1;
0N/A break;
0N/A case MLIB_BYTE:
6344N/A // wb is ready
0N/A mask = 0;
0N/A break;
0N/A case MLIB_BIT:
6344N/A if (!SAFE_TO_ADD(7, wb)) {
6344N/A return NULL;
6344N/A }
6344N/A wb = (wb + 7) / 8;
0N/A mask = 0;
0N/A break;
0N/A default:
0N/A return NULL;
0N/A }
0N/A
0N/A if (stride & mask) {
0N/A return NULL;
0N/A }
0N/A
0N/A image -> flags = ((width & 0xf) << 8); /* set width field */
0N/A image -> flags |= ((stride & 0xf) << 16); /* set stride field */
0N/A image -> flags |= ((height & 0xf) << 12); /* set height field */
0N/A image -> flags |= (mlib_addr)data & 0xff;
0N/A image -> flags |= MLIB_IMAGE_USERALLOCATED; /* user allocated data */
0N/A
0N/A if ((stride != wb) ||
0N/A ((type == MLIB_BIT) && (stride * 8 != width * channels))) {
0N/A image -> flags |= MLIB_IMAGE_ONEDVECTOR;
0N/A }
0N/A
0N/A image -> flags &= MLIB_IMAGE_ATTRIBUTESET;
0N/A
0N/A return image;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_image *mlib_ImageCreateStruct(mlib_type type,
0N/A mlib_s32 channels,
0N/A mlib_s32 width,
0N/A mlib_s32 height,
0N/A mlib_s32 stride,
0N/A const void *data)
0N/A{
0N/A mlib_image *image;
0N/A if (stride <= 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A image = (mlib_image *)mlib_malloc(sizeof(mlib_image));
0N/A if (image == NULL) {
0N/A return NULL;
0N/A }
0N/A
0N/A if (mlib_ImageSet(image, type, channels, width, height, stride, data) == NULL) {
0N/A mlib_free(image);
0N/A image = NULL;
0N/A }
0N/A
0N/A return image;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_image *mlib_ImageCreate(mlib_type type,
0N/A mlib_s32 channels,
0N/A mlib_s32 width,
0N/A mlib_s32 height)
0N/A{
0N/A mlib_image *image;
0N/A mlib_s32 wb; /* width in bytes */
0N/A void *data;
0N/A
0N/A/* sanity check */
0N/A if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {
0N/A return NULL;
0N/A };
0N/A
5817N/A if (!SAFE_TO_MULT(width, channels)) {
5817N/A return NULL;
5817N/A }
5817N/A
5817N/A wb = width * channels;
5817N/A
0N/A switch (type) {
0N/A case MLIB_DOUBLE:
5817N/A if (!SAFE_TO_MULT(wb, 8)) {
5817N/A return NULL;
5817N/A }
5817N/A wb *= 8;
0N/A break;
0N/A case MLIB_FLOAT:
0N/A case MLIB_INT:
5817N/A if (!SAFE_TO_MULT(wb, 4)) {
5817N/A return NULL;
5817N/A }
5817N/A wb *= 4;
0N/A break;
0N/A case MLIB_USHORT:
0N/A case MLIB_SHORT:
6344N/A if (!SAFE_TO_MULT(wb, 2)) {
5817N/A return NULL;
5817N/A }
5817N/A wb *= 2;
0N/A break;
0N/A case MLIB_BYTE:
5817N/A // wb is ready
0N/A break;
0N/A case MLIB_BIT:
5817N/A if (!SAFE_TO_ADD(7, wb)) {
5817N/A return NULL;
5817N/A }
5817N/A wb = (wb + 7) / 8;
0N/A break;
0N/A default:
0N/A return NULL;
0N/A }
0N/A
5817N/A if (!SAFE_TO_MULT(wb, height)) {
5817N/A return NULL;
5817N/A }
5817N/A
0N/A data = mlib_malloc(wb * height);
0N/A if (data == NULL) {
0N/A return NULL;
0N/A }
0N/A
0N/A image = (mlib_image *)mlib_malloc(sizeof(mlib_image));
0N/A if (image == NULL) {
0N/A mlib_free(data);
0N/A return NULL;
0N/A };
0N/A
0N/A image -> type = type;
0N/A image -> channels = channels;
0N/A image -> width = width;
0N/A image -> height = height;
0N/A image -> stride = wb;
0N/A image -> data = data;
0N/A image -> flags = ((width & 0xf) << 8); /* set width field */
0N/A image -> flags |= ((height & 0xf) << 12); /* set height field */
0N/A image -> flags |= ((wb & 0xf) << 16); /* set stride field */
0N/A image -> flags |= (mlib_addr)data & 0xff;
0N/A image -> format = MLIB_FORMAT_UNKNOWN;
0N/A
0N/A image -> paddings[0] = 0;
0N/A image -> paddings[1] = 0;
0N/A image -> paddings[2] = 0;
0N/A image -> paddings[3] = 0;
0N/A
0N/A image -> bitoffset = 0;
0N/A
0N/A if ((type == MLIB_BIT) && (wb * 8 != width * channels)) {
0N/A image -> flags |= MLIB_IMAGE_ONEDVECTOR; /* not 1-d vector */
0N/A }
0N/A
0N/A image -> flags &= MLIB_IMAGE_ATTRIBUTESET;
0N/A image -> state = NULL;
0N/A
0N/A return image;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageDelete(mlib_image *img)
0N/A{
0N/A if (img == NULL) return;
0N/A if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) {
0N/A mlib_free(img -> data);
0N/A }
0N/A
0N/A mlib_ImageDeleteRowTable(img);
0N/A mlib_free(img);
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_image *mlib_ImageCreateSubimage(mlib_image *img,
0N/A mlib_s32 x,
0N/A mlib_s32 y,
0N/A mlib_s32 w,
0N/A mlib_s32 h)
0N/A{
0N/A mlib_image *subimage;
0N/A mlib_type type;
0N/A mlib_s32 channels;
0N/A mlib_s32 width; /* for parent image */
0N/A mlib_s32 height; /* for parent image */
0N/A mlib_s32 stride;
3813N/A mlib_s32 bitoffset = 0;
0N/A void *data;
0N/A
0N/A/* sanity check */
0N/A if (w <= 0 || h <= 0 || img == NULL) return NULL;
0N/A
0N/A type = img -> type;
0N/A channels = img -> channels;
0N/A width = img -> width;
0N/A height = img -> height;
0N/A stride = img -> stride;
0N/A
0N/A/* clip the sub-image with respect to the parent image */
0N/A if (((x + w) <= 0) || ((y + h) <= 0) ||
0N/A (x >= width) || (y >= height)) {
0N/A return NULL;
0N/A }
0N/A else {
0N/A if (x < 0) {
0N/A w += x; /* x is negative */
0N/A x = 0;
0N/A }
0N/A
0N/A if (y < 0) {
0N/A h += y; /* y is negative */
0N/A y = 0;
0N/A }
0N/A
0N/A if ((x + w) > width) {
0N/A w = width - x;
0N/A }
0N/A
0N/A if ((y + h) > height) {
0N/A h = height - y;
0N/A }
0N/A }
0N/A
0N/A/* compute sub-image origin */
0N/A data = (mlib_u8 *)(img -> data) + y * stride;
0N/A
0N/A switch (type) {
0N/A case MLIB_DOUBLE:
0N/A data = (mlib_u8 *)data + x * channels * 8;
0N/A break;
0N/A case MLIB_FLOAT:
0N/A case MLIB_INT:
0N/A data = (mlib_u8 *)data + x * channels * 4;
0N/A break;
0N/A case MLIB_USHORT:
0N/A case MLIB_SHORT:
0N/A data = (mlib_u8 *)data + x * channels * 2;
0N/A break;
0N/A case MLIB_BYTE:
0N/A data = (mlib_u8 *)data + x * channels;
0N/A break;
0N/A case MLIB_BIT:
0N/A bitoffset = img -> bitoffset;
0N/A data = (mlib_u8 *)data + (x * channels + bitoffset) / 8;
0N/A bitoffset = (x * channels + bitoffset) & 7;
0N/A break;
0N/A default:
0N/A return NULL;
0N/A }
0N/A
0N/A subimage = mlib_ImageCreateStruct(type,
0N/A channels,
0N/A w,
0N/A h,
0N/A stride,
0N/A data);
0N/A
0N/A if (subimage != NULL && type == MLIB_BIT)
0N/A subimage -> bitoffset = bitoffset;
0N/A
0N/A return subimage;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_image *mlib_ImageSetSubimage(mlib_image *dst,
0N/A const mlib_image *src,
0N/A mlib_s32 x,
0N/A mlib_s32 y,
0N/A mlib_s32 w,
0N/A mlib_s32 h)
0N/A{
0N/A mlib_type type = src -> type;
0N/A mlib_s32 channels = src -> channels;
0N/A mlib_s32 stride = src -> stride;
0N/A mlib_u8 *data = src -> data;
3813N/A mlib_s32 bitoffset = 0;
0N/A
0N/A data += y * stride;
0N/A
0N/A switch (type) {
0N/A case MLIB_DOUBLE:
0N/A data += channels * x * 8;
0N/A break;
0N/A case MLIB_FLOAT:
0N/A case MLIB_INT:
0N/A data += channels * x * 4;
0N/A break;
0N/A case MLIB_USHORT:
0N/A case MLIB_SHORT:
0N/A data += channels * x * 2;
0N/A break;
0N/A case MLIB_BYTE:
0N/A data += channels * x;
0N/A break;
0N/A case MLIB_BIT:
0N/A bitoffset = src -> bitoffset + channels * x;
0N/A data += (bitoffset >= 0) ? bitoffset/8 : (bitoffset - 7)/8; /* with rounding toward -Inf */
0N/A bitoffset &= 7;
0N/A break;
0N/A default:
0N/A return NULL;
0N/A }
0N/A
0N/A if (h > 0) {
0N/A dst = mlib_ImageSet(dst, type, channels, w, h, stride, data);
0N/A } else {
0N/A h = - h;
0N/A dst = mlib_ImageSet(dst, type, channels, w, h, - stride, data + (h - 1)*stride);
0N/A }
0N/A
0N/A if (dst != NULL && type == MLIB_BIT) {
0N/A dst -> bitoffset = bitoffset;
0N/A }
0N/A
0N/A return dst;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid *mlib_ImageCreateRowTable(mlib_image *img)
0N/A{
0N/A mlib_u8 **rtable, *tline;
0N/A mlib_s32 i, im_height, im_stride;
0N/A
0N/A if (img == NULL) return NULL;
0N/A if (img -> state) return img -> state;
0N/A
0N/A im_height = mlib_ImageGetHeight(img);
0N/A im_stride = mlib_ImageGetStride(img);
0N/A tline = mlib_ImageGetData(img);
0N/A rtable = mlib_malloc((3 + im_height)*sizeof(mlib_u8 *));
0N/A
0N/A if (rtable == NULL || tline == NULL) return NULL;
0N/A
0N/A rtable[0] = 0;
0N/A rtable[1] = (mlib_u8*)((void **)rtable + 1);
0N/A rtable[2 + im_height] = (mlib_u8*)((void **)rtable + 1);
0N/A for (i = 0; i < im_height; i++) {
0N/A rtable[i+2] = tline;
0N/A tline += im_stride;
0N/A }
0N/A
0N/A img -> state = ((void **)rtable + 2);
0N/A return img -> state;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageDeleteRowTable(mlib_image *img)
0N/A{
0N/A void **state;
0N/A
0N/A if (img == NULL) return;
0N/A
0N/A state = img -> state;
0N/A if (!state) return;
0N/A
0N/A mlib_free(state - 2);
0N/A img -> state = 0;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_status mlib_ImageSetPaddings(mlib_image *img,
0N/A mlib_u8 left,
0N/A mlib_u8 top,
0N/A mlib_u8 right,
0N/A mlib_u8 bottom)
0N/A{
0N/A if (img == NULL) return MLIB_FAILURE;
0N/A
0N/A if ((left + right) >= img -> width ||
0N/A (top + bottom) >= img -> height) return MLIB_OUTOFRANGE;
0N/A
0N/A img -> paddings[0] = left;
0N/A img -> paddings[1] = top;
0N/A img -> paddings[2] = right;
0N/A img -> paddings[3] = bottom;
0N/A
0N/A return MLIB_SUCCESS;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_status mlib_ImageSetFormat(mlib_image *img,
0N/A mlib_format format)
0N/A{
0N/A if (img == NULL) return MLIB_FAILURE;
0N/A
0N/A img -> format = format;
0N/A
0N/A return MLIB_SUCCESS;
0N/A}
0N/A
0N/A/***************************************************************/