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