1 /*------------------------------------------------------------------------- 2 * drawElements Image Library 3 * -------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Image library. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "deImage.h" 25 #include "deMemory.h" 26 #include "deInt32.h" 27 #include "deMath.h" 28 29 static int deImageFormat_getBytesPerPixel (deImageFormat format) 30 { 31 DE_ASSERT(format == DE_IMAGEFORMAT_XRGB8888 || format == DE_IMAGEFORMAT_ARGB8888); 32 DE_UNREF(format); 33 return 4; 34 } 35 36 static void* getPixelAddress (const deImage* image, int x, int y) 37 { 38 int offset = ((y*image->width) + x) * deImageFormat_getBytesPerPixel(image->format); 39 DE_ASSERT(deInBounds32(x, 0, image->width)); 40 DE_ASSERT(deInBounds32(y, 0, image->height)); 41 return (void*)((deUint8*)image->pixels + offset); 42 } 43 44 deImage* deImage_create (int width, int height, deImageFormat format) 45 { 46 deImage* image = DE_NEW(deImage); 47 int bpp = deImageFormat_getBytesPerPixel(format); 48 if (!image) 49 return DE_NULL; 50 51 image->width = width; 52 image->height = height; 53 image->format = format; 54 image->pixels = deMalloc(width * height * bpp); 55 if (!image->pixels) 56 { 57 deFree(image); 58 return DE_NULL; 59 } 60 memset(image->pixels, 0, width * height * bpp); 61 62 return image; 63 } 64 65 void deImage_destroy (deImage* image) 66 { 67 deFree(image->pixels); 68 deFree(image); 69 } 70 71 deARGB deImage_getPixel (const deImage* image, int x, int y) 72 { 73 void* addr = getPixelAddress(image, x, y); 74 switch (image->format) 75 { 76 case DE_IMAGEFORMAT_XRGB8888: return *(deARGB*)addr; 77 case DE_IMAGEFORMAT_ARGB8888: return *(deARGB*)addr; 78 default: 79 DE_FATAL("deImage_getPixel(): invalid format"); 80 return deARGB_black(); 81 } 82 } 83 84 void deImage_setPixel (deImage* image, int x, int y, deARGB argb) 85 { 86 void* addr = getPixelAddress(image, x, y); 87 switch (image->format) 88 { 89 case DE_IMAGEFORMAT_XRGB8888: *(deARGB*)addr = argb; break; 90 case DE_IMAGEFORMAT_ARGB8888: *(deARGB*)addr = argb; break; 91 default: 92 DE_FATAL("deImage_getPixel(): invalid format"); 93 } 94 } 95 96 deImage* deImage_convertFormat (const deImage* image, deImageFormat format) 97 { 98 int width = image->width; 99 int height = image->height; 100 deImage* converted = deImage_create(width, height, format); 101 if (!converted) 102 return DE_NULL; 103 104 if (format == image->format) 105 memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format)); 106 else 107 { 108 int x, y; 109 for (y = 0; y < height; y++) 110 for (x = 0; x < width; x++) 111 deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y)); 112 } 113 114 return converted; 115 } 116 117 deImage* deImage_scale (const deImage* srcImage, int dstWidth, int dstHeight) 118 { 119 int srcWidth = srcImage->width; 120 int srcHeight = srcImage->height; 121 deImage* result = deImage_create(dstWidth, dstHeight, srcImage->format); 122 int x, y; 123 124 for (y = 0; y < dstHeight; y++) 125 { 126 for (x = 0; x < dstWidth; x++) 127 { 128 float xFloat = ((float)x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f; 129 float yFloat = ((float)y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f; 130 int xFixed = deFloorFloatToInt32(xFloat * 256.0f); 131 int yFixed = deFloorFloatToInt32(yFloat * 256.0f); 132 int xFactor = (xFixed & 0xFF); 133 int yFactor = (yFixed & 0xFF); 134 int f00 = ((256-xFactor) * (256-yFactor)) >> 8; 135 int f10 = ((256-xFactor) * yFactor) >> 8; 136 int f01 = (xFactor * (256-yFactor)) >> 8; 137 int f11 = (xFactor * yFactor) >> 8; 138 int x0 = (xFixed >> 8); 139 int y0 = (yFixed >> 8); 140 int x1 = deClamp32(x0+1, 0, srcWidth-1); 141 int y1 = deClamp32(y0+1, 0, srcHeight-1); 142 DE_ASSERT(deInBounds32(x0, 0, srcWidth)); 143 DE_ASSERT(deInBounds32(y0, 0, srcHeight)); 144 145 /* Filtering. */ 146 { 147 deARGB p00 = deImage_getPixel(srcImage, x0, y0); 148 deARGB p10 = deImage_getPixel(srcImage, x1, y0); 149 deARGB p01 = deImage_getPixel(srcImage, x0, y1); 150 deARGB p11 = deImage_getPixel(srcImage, x1, y1); 151 deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)), 152 deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11))); 153 deImage_setPixel(result, x, y, pix); 154 } 155 } 156 } 157 158 return result; 159 } 160 161 void deImage_copyToUint8RGBA (const deImage* image, deUint8* pixels) 162 { 163 int width = image->width; 164 int height = image->height; 165 int x,y; 166 167 for (y = 0; y < height; y++) 168 for (x = 0; x < width; x++) 169 { 170 deARGB pixel = deImage_getPixel(image, x, y); 171 int ndx = (y * width) + x; 172 pixels[4*ndx+0] = (deUint8)deARGB_getRed(pixel); 173 pixels[4*ndx+1] = (deUint8)deARGB_getGreen(pixel); 174 pixels[4*ndx+2] = (deUint8)deARGB_getBlue(pixel); 175 pixels[4*ndx+3] = (deUint8)deARGB_getAlpha(pixel); 176 } 177 } 178 179 void* deImage_getPixelPtr (const deImage* image) 180 { 181 return image->pixels; 182 } 183 184 int deImage_getWidth (const deImage* image) 185 { 186 return image->width; 187 } 188 189 int deImage_getHeight (const deImage* image) 190 { 191 return image->height; 192 } 193