13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Image Library 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Image library. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deImage.h" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int deImageFormat_getBytesPerPixel (deImageFormat format) 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(format == DE_IMAGEFORMAT_XRGB8888 || format == DE_IMAGEFORMAT_ARGB8888); 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(format); 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 4; 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void* getPixelAddress (const deImage* image, int x, int y) 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int offset = ((y*image->width) + x) * deImageFormat_getBytesPerPixel(image->format); 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(deInBounds32(x, 0, image->width)); 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(deInBounds32(y, 0, image->height)); 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (void*)((deUint8*)image->pixels + offset); 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 443c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_create (int width, int height, deImageFormat format) 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage* image = DE_NEW(deImage); 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bpp = deImageFormat_getBytesPerPixel(format); 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!image) 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image->width = width; 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image->height = height; 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image->format = format; 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image->pixels = deMalloc(width * height * bpp); 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!image->pixels) 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deFree(image); 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memset(image->pixels, 0, width * height * bpp); 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return image; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_destroy (deImage* image) 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deFree(image->pixels); 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deFree(image); 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 713c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeARGB deImage_getPixel (const deImage* image, int x, int y) 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* addr = getPixelAddress(image, x, y); 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (image->format) 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case DE_IMAGEFORMAT_XRGB8888: return *(deARGB*)addr; 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case DE_IMAGEFORMAT_ARGB8888: return *(deARGB*)addr; 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 791cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry DE_FATAL("deImage_getPixel(): invalid format"); 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return deARGB_black(); 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_setPixel (deImage* image, int x, int y, deARGB argb) 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* addr = getPixelAddress(image, x, y); 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (image->format) 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case DE_IMAGEFORMAT_XRGB8888: *(deARGB*)addr = argb; break; 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case DE_IMAGEFORMAT_ARGB8888: *(deARGB*)addr = argb; break; 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 921cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry DE_FATAL("deImage_getPixel(): invalid format"); 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 963c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_convertFormat (const deImage* image, deImageFormat format) 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int width = image->width; 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int height = image->height; 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage* converted = deImage_create(width, height, format); 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!converted) 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_NULL; 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (format == image->format) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format)); 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x, y; 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (y = 0; y < height; y++) 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (x = 0; x < width; x++) 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y)); 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return converted; 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1173c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_scale (const deImage* srcImage, int dstWidth, int dstHeight) 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int srcWidth = srcImage->width; 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int srcHeight = srcImage->height; 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage* result = deImage_create(dstWidth, dstHeight, srcImage->format); 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x, y; 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (y = 0; y < dstHeight; y++) 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (x = 0; x < dstWidth; x++) 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1286545ee9f6c68d14c63965e8902eafac8b4ee35f8Jarkko Pöyry float xFloat = ((float)x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f; 1296545ee9f6c68d14c63965e8902eafac8b4ee35f8Jarkko Pöyry float yFloat = ((float)y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f; 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int xFixed = deFloorFloatToInt32(xFloat * 256.0f); 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int yFixed = deFloorFloatToInt32(yFloat * 256.0f); 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int xFactor = (xFixed & 0xFF); 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int yFactor = (yFixed & 0xFF); 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int f00 = ((256-xFactor) * (256-yFactor)) >> 8; 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int f10 = ((256-xFactor) * yFactor) >> 8; 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int f01 = (xFactor * (256-yFactor)) >> 8; 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int f11 = (xFactor * yFactor) >> 8; 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x0 = (xFixed >> 8); 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int y0 = (yFixed >> 8); 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x1 = deClamp32(x0+1, 0, srcWidth-1); 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int y1 = deClamp32(y0+1, 0, srcHeight-1); 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(deInBounds32(x0, 0, srcWidth)); 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(deInBounds32(y0, 0, srcHeight)); 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Filtering. */ 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB p00 = deImage_getPixel(srcImage, x0, y0); 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB p10 = deImage_getPixel(srcImage, x1, y0); 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB p01 = deImage_getPixel(srcImage, x0, y1); 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB p11 = deImage_getPixel(srcImage, x1, y1); 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)), 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11))); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage_setPixel(result, x, y, pix); 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return result; 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_copyToUint8RGBA (const deImage* image, deUint8* pixels) 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int width = image->width; 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int height = image->height; 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x,y; 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (y = 0; y < height; y++) 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (x = 0; x < width; x++) 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB pixel = deImage_getPixel(image, x, y); 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int ndx = (y * width) + x; 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixels[4*ndx+0] = (deUint8)deARGB_getRed(pixel); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixels[4*ndx+1] = (deUint8)deARGB_getGreen(pixel); 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixels[4*ndx+2] = (deUint8)deARGB_getBlue(pixel); 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixels[4*ndx+3] = (deUint8)deARGB_getAlpha(pixel); 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid* deImage_getPixelPtr (const deImage* image) 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return image->pixels; 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deImage_getWidth (const deImage* image) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return image->width; 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deImage_getHeight (const deImage* image) 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return image->height; 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 193