/*------------------------------------------------------------------------- * drawElements Image Library * -------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Image library. *//*--------------------------------------------------------------------*/ #include "deImage.h" #include "deMemory.h" #include "deInt32.h" #include "deMath.h" static int deImageFormat_getBytesPerPixel (deImageFormat format) { DE_ASSERT(format == DE_IMAGEFORMAT_XRGB8888 || format == DE_IMAGEFORMAT_ARGB8888); DE_UNREF(format); return 4; } static void* getPixelAddress (const deImage* image, int x, int y) { int offset = ((y*image->width) + x) * deImageFormat_getBytesPerPixel(image->format); DE_ASSERT(deInBounds32(x, 0, image->width)); DE_ASSERT(deInBounds32(y, 0, image->height)); return (void*)((deUint8*)image->pixels + offset); } deImage* deImage_create (int width, int height, deImageFormat format) { deImage* image = DE_NEW(deImage); int bpp = deImageFormat_getBytesPerPixel(format); if (!image) return DE_NULL; image->width = width; image->height = height; image->format = format; image->pixels = deMalloc(width * height * bpp); if (!image->pixels) { deFree(image); return DE_NULL; } memset(image->pixels, 0, width * height * bpp); return image; } void deImage_destroy (deImage* image) { deFree(image->pixels); deFree(image); } deARGB deImage_getPixel (const deImage* image, int x, int y) { void* addr = getPixelAddress(image, x, y); switch (image->format) { case DE_IMAGEFORMAT_XRGB8888: return *(deARGB*)addr; case DE_IMAGEFORMAT_ARGB8888: return *(deARGB*)addr; default: DE_FATAL("deImage_getPixel(): invalid format"); return deARGB_black(); } } void deImage_setPixel (deImage* image, int x, int y, deARGB argb) { void* addr = getPixelAddress(image, x, y); switch (image->format) { case DE_IMAGEFORMAT_XRGB8888: *(deARGB*)addr = argb; break; case DE_IMAGEFORMAT_ARGB8888: *(deARGB*)addr = argb; break; default: DE_FATAL("deImage_getPixel(): invalid format"); } } deImage* deImage_convertFormat (const deImage* image, deImageFormat format) { int width = image->width; int height = image->height; deImage* converted = deImage_create(width, height, format); if (!converted) return DE_NULL; if (format == image->format) memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format)); else { int x, y; for (y = 0; y < height; y++) for (x = 0; x < width; x++) deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y)); } return converted; } deImage* deImage_scale (const deImage* srcImage, int dstWidth, int dstHeight) { int srcWidth = srcImage->width; int srcHeight = srcImage->height; deImage* result = deImage_create(dstWidth, dstHeight, srcImage->format); int x, y; for (y = 0; y < dstHeight; y++) { for (x = 0; x < dstWidth; x++) { float xFloat = ((float)x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f; float yFloat = ((float)y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f; int xFixed = deFloorFloatToInt32(xFloat * 256.0f); int yFixed = deFloorFloatToInt32(yFloat * 256.0f); int xFactor = (xFixed & 0xFF); int yFactor = (yFixed & 0xFF); int f00 = ((256-xFactor) * (256-yFactor)) >> 8; int f10 = ((256-xFactor) * yFactor) >> 8; int f01 = (xFactor * (256-yFactor)) >> 8; int f11 = (xFactor * yFactor) >> 8; int x0 = (xFixed >> 8); int y0 = (yFixed >> 8); int x1 = deClamp32(x0+1, 0, srcWidth-1); int y1 = deClamp32(y0+1, 0, srcHeight-1); DE_ASSERT(deInBounds32(x0, 0, srcWidth)); DE_ASSERT(deInBounds32(y0, 0, srcHeight)); /* Filtering. */ { deARGB p00 = deImage_getPixel(srcImage, x0, y0); deARGB p10 = deImage_getPixel(srcImage, x1, y0); deARGB p01 = deImage_getPixel(srcImage, x0, y1); deARGB p11 = deImage_getPixel(srcImage, x1, y1); deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)), deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11))); deImage_setPixel(result, x, y, pix); } } } return result; } void deImage_copyToUint8RGBA (const deImage* image, deUint8* pixels) { int width = image->width; int height = image->height; int x,y; for (y = 0; y < height; y++) for (x = 0; x < width; x++) { deARGB pixel = deImage_getPixel(image, x, y); int ndx = (y * width) + x; pixels[4*ndx+0] = (deUint8)deARGB_getRed(pixel); pixels[4*ndx+1] = (deUint8)deARGB_getGreen(pixel); pixels[4*ndx+2] = (deUint8)deARGB_getBlue(pixel); pixels[4*ndx+3] = (deUint8)deARGB_getAlpha(pixel); } } void* deImage_getPixelPtr (const deImage* image) { return image->pixels; } int deImage_getWidth (const deImage* image) { return image->width; } int deImage_getHeight (const deImage* image) { return image->height; }