Path: blob/master/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c
41161 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526/*27* FUNCTION28* mlib_ImageCreateStruct - create image data structure29* mlib_ImageCreate - create image data structure and allocate30* memory for image data31* mlib_ImageDelete - delete image32* mlib_ImageCreateSubimage - create sub-image33*34* mlib_ImageCreateRowTable - create row starts pointer table35* mlib_ImageDeleteRowTable - delete row starts pointer table36*37* mlib_ImageSetPaddings - set paddings for clipping box borders38*39* mlib_ImageSetFormat - set image format40*41* SYNOPSIS42* mlib_image *mlib_ImageCreateStruct(mlib_type type,43* mlib_s32 channels,44* mlib_s32 width,45* mlib_s32 height,46* mlib_s32 stride,47* const void *data)48*49* mlib_image *mlib_ImageCreate(mlib_type type,50* mlib_s32 channels,51* mlib_s32 width,52* mlib_s32 height)53*54* void mlib_ImageDelete(mlib_image *img)55*56* mlib_image *mlib_ImageCreateSubimage(mlib_image *img,57* mlib_s32 x,58* mlib_s32 y,59* mlib_s32 w,60* mlib_s32 h)61*62* void *mlib_ImageCreateRowTable(mlib_image *img)63*64* void mlib_ImageDeleteRowTable(mlib_image *img)65*66* mlib_status mlib_ImageSetPaddings(mlib_image *img,67* mlib_u8 left,68* mlib_u8 top,69* mlib_u8 right,70* mlib_u8 bottom)71*72* mlib_status mlib_ImageSetFormat(mlib_image *img,73* mlib_format format)74* ARGUMENTS75* img pointer to image data structure76* type image data type, one of MLIB_BIT, MLIB_BYTE, MLIB_SHORT,77* MLIB_USHORT, MLIB_INT, MLIB_FLOAT or MLIB_DOUBLE78* channels number of image channels79* width image width in pixels80* height image height in pixels81* stride linebytes( bytes to next row) of the image82* data pointer to image data allocated by user83* x x coordinate of the left border in the source image84* y y coordinate of the top border in the source image85* w width of the sub-image86* h height of the sub-image87* left clipping box left padding88* top clipping box top padding89* right clipping box right padding90* bottom clipping box bottom padding91* format image format92*93* DESCRIPTION94* mlib_ImageCreateStruct() creates a mediaLib image data structure95* using parameter supplied by user.96*97* mlib_ImageCreate() creates a mediaLib image data structure and98* allocates memory space for image data.99*100* mlib_ImageDelete() deletes the mediaLib image data structure101* and frees the memory space of the image data if it is allocated102* through mlib_ImageCreate().103*104* mlib_ImageCreateSubimage() creates a mediaLib image structure105* for a sub-image based on a source image.106*107* mlib_ImageCreateRowTable() creates row starts pointer table and108* puts it into mlib_image->state field.109*110* mlib_ImageDeleteRowTable() deletes row starts pointer table from111* image and puts NULL into mlib_image->state field.112*113* mlib_ImageSetPaddings() sets new values for the clipping box paddings114*115* mlib_ImageSetFormat() sets new value for the image format116*/117118#include <stdlib.h>119#include "mlib_image.h"120#include "mlib_ImageRowTable.h"121#include "mlib_ImageCreate.h"122#include "safe_math.h"123124/***************************************************************/125mlib_image* mlib_ImageSet(mlib_image *image,126mlib_type type,127mlib_s32 channels,128mlib_s32 width,129mlib_s32 height,130mlib_s32 stride,131const void *data)132{133mlib_s32 wb; /* width in bytes */134mlib_s32 mask; /* mask for check of stride */135136if (image == NULL) return NULL;137138/* for some ugly functions calling with incorrect parameters */139image -> type = type;140image -> channels = channels;141image -> width = width;142image -> height = height;143image -> stride = stride;144image -> data = (void *)data;145image -> state = NULL;146image -> format = MLIB_FORMAT_UNKNOWN;147148image -> paddings[0] = 0;149image -> paddings[1] = 0;150image -> paddings[2] = 0;151image -> paddings[3] = 0;152153image -> bitoffset = 0;154155if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {156return NULL;157}158159/* Check if stride == width160* If it is then image can be treated as a 1-D vector161*/162163if (!SAFE_TO_MULT(width, channels)) {164return NULL;165}166167wb = width * channels;168169switch (type) {170case MLIB_DOUBLE:171if (!SAFE_TO_MULT(wb, 8)) {172return NULL;173}174wb *= 8;175mask = 7;176break;177case MLIB_FLOAT:178case MLIB_INT:179if (!SAFE_TO_MULT(wb, 4)) {180return NULL;181}182wb *= 4;183mask = 3;184break;185case MLIB_USHORT:186case MLIB_SHORT:187if (!SAFE_TO_MULT(wb, 2)) {188return NULL;189}190wb *= 2;191mask = 1;192break;193case MLIB_BYTE:194// wb is ready195mask = 0;196break;197case MLIB_BIT:198if (!SAFE_TO_ADD(7, wb)) {199return NULL;200}201wb = (wb + 7) / 8;202mask = 0;203break;204default:205return NULL;206}207208if (stride & mask) {209return NULL;210}211212image -> flags = ((width & 0xf) << 8); /* set width field */213image -> flags |= ((stride & 0xf) << 16); /* set stride field */214image -> flags |= ((height & 0xf) << 12); /* set height field */215image -> flags |= (mlib_addr)data & 0xff;216image -> flags |= MLIB_IMAGE_USERALLOCATED; /* user allocated data */217218if ((stride != wb) ||219((type == MLIB_BIT) && (stride * 8 != width * channels))) {220image -> flags |= MLIB_IMAGE_ONEDVECTOR;221}222223image -> flags &= MLIB_IMAGE_ATTRIBUTESET;224225return image;226}227228/***************************************************************/229JNIEXPORT230mlib_image* mlib_ImageCreateStruct(mlib_type type,231mlib_s32 channels,232mlib_s32 width,233mlib_s32 height,234mlib_s32 stride,235const void *data)236{237mlib_image *image;238if (stride <= 0) {239return NULL;240}241242image = (mlib_image *)mlib_malloc(sizeof(mlib_image));243if (image == NULL) {244return NULL;245}246247if (mlib_ImageSet(image, type, channels, width, height, stride, data) == NULL) {248mlib_free(image);249image = NULL;250}251252return image;253}254255/***************************************************************/256JNIEXPORT257mlib_image* mlib_ImageCreate(mlib_type type,258mlib_s32 channels,259mlib_s32 width,260mlib_s32 height)261{262mlib_image *image;263mlib_s32 wb; /* width in bytes */264void *data;265266/* sanity check */267if (width <= 0 || height <= 0 || channels < 1 || channels > 4) {268return NULL;269};270271if (!SAFE_TO_MULT(width, channels)) {272return NULL;273}274275wb = width * channels;276277switch (type) {278case MLIB_DOUBLE:279if (!SAFE_TO_MULT(wb, 8)) {280return NULL;281}282wb *= 8;283break;284case MLIB_FLOAT:285case MLIB_INT:286if (!SAFE_TO_MULT(wb, 4)) {287return NULL;288}289wb *= 4;290break;291case MLIB_USHORT:292case MLIB_SHORT:293if (!SAFE_TO_MULT(wb, 2)) {294return NULL;295}296wb *= 2;297break;298case MLIB_BYTE:299// wb is ready300break;301case MLIB_BIT:302if (!SAFE_TO_ADD(7, wb)) {303return NULL;304}305wb = (wb + 7) / 8;306break;307default:308return NULL;309}310311if (!SAFE_TO_MULT(wb, height)) {312return NULL;313}314315data = mlib_malloc(wb * height);316if (data == NULL) {317return NULL;318}319320image = (mlib_image *)mlib_malloc(sizeof(mlib_image));321if (image == NULL) {322mlib_free(data);323return NULL;324};325326image -> type = type;327image -> channels = channels;328image -> width = width;329image -> height = height;330image -> stride = wb;331image -> data = data;332image -> flags = ((width & 0xf) << 8); /* set width field */333image -> flags |= ((height & 0xf) << 12); /* set height field */334image -> flags |= ((wb & 0xf) << 16); /* set stride field */335image -> flags |= (mlib_addr)data & 0xff;336image -> format = MLIB_FORMAT_UNKNOWN;337338image -> paddings[0] = 0;339image -> paddings[1] = 0;340image -> paddings[2] = 0;341image -> paddings[3] = 0;342343image -> bitoffset = 0;344345if ((type == MLIB_BIT) && (wb * 8 != width * channels)) {346image -> flags |= MLIB_IMAGE_ONEDVECTOR; /* not 1-d vector */347}348349image -> flags &= MLIB_IMAGE_ATTRIBUTESET;350image -> state = NULL;351352return image;353}354355/***************************************************************/356JNIEXPORT357void mlib_ImageDelete(mlib_image *img)358{359if (img == NULL) return;360if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) {361mlib_free(img -> data);362}363364mlib_ImageDeleteRowTable(img);365mlib_free(img);366}367368/***************************************************************/369mlib_image *mlib_ImageCreateSubimage(mlib_image *img,370mlib_s32 x,371mlib_s32 y,372mlib_s32 w,373mlib_s32 h)374{375mlib_image *subimage;376mlib_type type;377mlib_s32 channels;378mlib_s32 width; /* for parent image */379mlib_s32 height; /* for parent image */380mlib_s32 stride;381mlib_s32 bitoffset = 0;382void *data;383384/* sanity check */385if (w <= 0 || h <= 0 || img == NULL) return NULL;386387type = img -> type;388channels = img -> channels;389width = img -> width;390height = img -> height;391stride = img -> stride;392393/* clip the sub-image with respect to the parent image */394if (((x + w) <= 0) || ((y + h) <= 0) ||395(x >= width) || (y >= height)) {396return NULL;397}398else {399if (x < 0) {400w += x; /* x is negative */401x = 0;402}403404if (y < 0) {405h += y; /* y is negative */406y = 0;407}408409if ((x + w) > width) {410w = width - x;411}412413if ((y + h) > height) {414h = height - y;415}416}417418/* compute sub-image origin */419data = (mlib_u8 *)(img -> data) + y * stride;420421switch (type) {422case MLIB_DOUBLE:423data = (mlib_u8 *)data + x * channels * 8;424break;425case MLIB_FLOAT:426case MLIB_INT:427data = (mlib_u8 *)data + x * channels * 4;428break;429case MLIB_USHORT:430case MLIB_SHORT:431data = (mlib_u8 *)data + x * channels * 2;432break;433case MLIB_BYTE:434data = (mlib_u8 *)data + x * channels;435break;436case MLIB_BIT:437bitoffset = img -> bitoffset;438data = (mlib_u8 *)data + (x * channels + bitoffset) / 8;439bitoffset = (x * channels + bitoffset) & 7;440break;441default:442return NULL;443}444445subimage = mlib_ImageCreateStruct(type,446channels,447w,448h,449stride,450data);451452if (subimage != NULL && type == MLIB_BIT)453subimage -> bitoffset = bitoffset;454455return subimage;456}457458/***************************************************************/459mlib_image *mlib_ImageSetSubimage(mlib_image *dst,460const mlib_image *src,461mlib_s32 x,462mlib_s32 y,463mlib_s32 w,464mlib_s32 h)465{466mlib_type type = src -> type;467mlib_s32 channels = src -> channels;468mlib_s32 stride = src -> stride;469mlib_u8 *data = src -> data;470mlib_s32 bitoffset = 0;471472data += y * stride;473474switch (type) {475case MLIB_DOUBLE:476data += channels * x * 8;477break;478case MLIB_FLOAT:479case MLIB_INT:480data += channels * x * 4;481break;482case MLIB_USHORT:483case MLIB_SHORT:484data += channels * x * 2;485break;486case MLIB_BYTE:487data += channels * x;488break;489case MLIB_BIT:490bitoffset = src -> bitoffset + channels * x;491data += (bitoffset >= 0) ? bitoffset/8 : (bitoffset - 7)/8; /* with rounding toward -Inf */492bitoffset &= 7;493break;494default:495return NULL;496}497498if (h > 0) {499dst = mlib_ImageSet(dst, type, channels, w, h, stride, data);500} else {501h = - h;502dst = mlib_ImageSet(dst, type, channels, w, h, - stride, data + (h - 1)*stride);503}504505if (dst != NULL && type == MLIB_BIT) {506dst -> bitoffset = bitoffset;507}508509return dst;510}511512/***************************************************************/513void *mlib_ImageCreateRowTable(mlib_image *img)514{515mlib_u8 **rtable, *tline;516mlib_s32 i, im_height, im_stride;517518if (img == NULL) return NULL;519if (img -> state) return img -> state;520521im_height = mlib_ImageGetHeight(img);522im_stride = mlib_ImageGetStride(img);523tline = mlib_ImageGetData(img);524if (tline == NULL) return NULL;525rtable = mlib_malloc((3 + im_height)*sizeof(mlib_u8 *));526if (rtable == NULL) return NULL;527528rtable[0] = 0;529rtable[1] = (mlib_u8*)((void **)rtable + 1);530rtable[2 + im_height] = (mlib_u8*)((void **)rtable + 1);531for (i = 0; i < im_height; i++) {532rtable[i+2] = tline;533tline += im_stride;534}535536img -> state = ((void **)rtable + 2);537return img -> state;538}539540/***************************************************************/541void mlib_ImageDeleteRowTable(mlib_image *img)542{543void **state;544545if (img == NULL) return;546547state = img -> state;548if (!state) return;549550mlib_free(state - 2);551img -> state = 0;552}553554/***************************************************************/555mlib_status mlib_ImageSetPaddings(mlib_image *img,556mlib_u8 left,557mlib_u8 top,558mlib_u8 right,559mlib_u8 bottom)560{561if (img == NULL) return MLIB_FAILURE;562563if ((left + right) >= img -> width ||564(top + bottom) >= img -> height) return MLIB_OUTOFRANGE;565566img -> paddings[0] = left;567img -> paddings[1] = top;568img -> paddings[2] = right;569img -> paddings[3] = bottom;570571return MLIB_SUCCESS;572}573574/***************************************************************/575mlib_status mlib_ImageSetFormat(mlib_image *img,576mlib_format format)577{578if (img == NULL) return MLIB_FAILURE;579580img -> format = format;581582return MLIB_SUCCESS;583}584585/***************************************************************/586587588