Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / framework / delibs / deimage / deImage.c
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 }