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 
deImageFormat_getBytesPerPixel(deImageFormat format)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 
getPixelAddress(const deImage * image,int x,int y)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 
deImage_create(int width,int height,deImageFormat format)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 
deImage_destroy(deImage * image)65 void deImage_destroy (deImage* image)
66 {
67 	deFree(image->pixels);
68 	deFree(image);
69 }
70 
deImage_getPixel(const deImage * image,int x,int y)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 
deImage_setPixel(deImage * image,int x,int y,deARGB argb)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 
deImage_convertFormat(const deImage * image,deImageFormat format)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 
deImage_scale(const deImage * srcImage,int dstWidth,int dstHeight)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 
deImage_copyToUint8RGBA(const deImage * image,deUint8 * pixels)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 
deImage_getPixelPtr(const deImage * image)179 void* deImage_getPixelPtr (const deImage* image)
180 {
181 	return image->pixels;
182 }
183 
deImage_getWidth(const deImage * image)184 int deImage_getWidth (const deImage* image)
185 {
186 	return image->width;
187 }
188 
deImage_getHeight(const deImage * image)189 int deImage_getHeight (const deImage* image)
190 {
191 	return image->height;
192 }
193