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