xref: /aosp_15_r20/external/deqp/framework/delibs/deimage/deImage.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 *)((uint8_t *)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:
77         return *(deARGB *)addr;
78     case DE_IMAGEFORMAT_ARGB8888:
79         return *(deARGB *)addr;
80     default:
81         DE_FATAL("deImage_getPixel(): invalid format");
82         return deARGB_black();
83     }
84 }
85 
deImage_setPixel(deImage * image,int x,int y,deARGB argb)86 void deImage_setPixel(deImage *image, int x, int y, deARGB argb)
87 {
88     void *addr = getPixelAddress(image, x, y);
89     switch (image->format)
90     {
91     case DE_IMAGEFORMAT_XRGB8888:
92         *(deARGB *)addr = argb;
93         break;
94     case DE_IMAGEFORMAT_ARGB8888:
95         *(deARGB *)addr = argb;
96         break;
97     default:
98         DE_FATAL("deImage_getPixel(): invalid format");
99     }
100 }
101 
deImage_convertFormat(const deImage * image,deImageFormat format)102 deImage *deImage_convertFormat(const deImage *image, deImageFormat format)
103 {
104     int width          = image->width;
105     int height         = image->height;
106     deImage *converted = deImage_create(width, height, format);
107     if (!converted)
108         return DE_NULL;
109 
110     if (format == image->format)
111         memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format));
112     else
113     {
114         int x, y;
115         for (y = 0; y < height; y++)
116             for (x = 0; x < width; x++)
117                 deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y));
118     }
119 
120     return converted;
121 }
122 
deImage_scale(const deImage * srcImage,int dstWidth,int dstHeight)123 deImage *deImage_scale(const deImage *srcImage, int dstWidth, int dstHeight)
124 {
125     int srcWidth    = srcImage->width;
126     int srcHeight   = srcImage->height;
127     deImage *result = deImage_create(dstWidth, dstHeight, srcImage->format);
128     int x, y;
129 
130     for (y = 0; y < dstHeight; y++)
131     {
132         for (x = 0; x < dstWidth; x++)
133         {
134             float xFloat = ((float)x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f;
135             float yFloat = ((float)y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f;
136             int xFixed   = deFloorFloatToInt32(xFloat * 256.0f);
137             int yFixed   = deFloorFloatToInt32(yFloat * 256.0f);
138             int xFactor  = (xFixed & 0xFF);
139             int yFactor  = (yFixed & 0xFF);
140             int f00      = ((256 - xFactor) * (256 - yFactor)) >> 8;
141             int f10      = ((256 - xFactor) * yFactor) >> 8;
142             int f01      = (xFactor * (256 - yFactor)) >> 8;
143             int f11      = (xFactor * yFactor) >> 8;
144             int x0       = (xFixed >> 8);
145             int y0       = (yFixed >> 8);
146             int x1       = deClamp32(x0 + 1, 0, srcWidth - 1);
147             int y1       = deClamp32(y0 + 1, 0, srcHeight - 1);
148             DE_ASSERT(deInBounds32(x0, 0, srcWidth));
149             DE_ASSERT(deInBounds32(y0, 0, srcHeight));
150 
151             /* Filtering. */
152             {
153                 deARGB p00 = deImage_getPixel(srcImage, x0, y0);
154                 deARGB p10 = deImage_getPixel(srcImage, x1, y0);
155                 deARGB p01 = deImage_getPixel(srcImage, x0, y1);
156                 deARGB p11 = deImage_getPixel(srcImage, x1, y1);
157                 deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)),
158                                         deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11)));
159                 deImage_setPixel(result, x, y, pix);
160             }
161         }
162     }
163 
164     return result;
165 }
166 
deImage_copyToUint8RGBA(const deImage * image,uint8_t * pixels)167 void deImage_copyToUint8RGBA(const deImage *image, uint8_t *pixels)
168 {
169     int width  = image->width;
170     int height = image->height;
171     int x, y;
172 
173     for (y = 0; y < height; y++)
174         for (x = 0; x < width; x++)
175         {
176             deARGB pixel        = deImage_getPixel(image, x, y);
177             int ndx             = (y * width) + x;
178             pixels[4 * ndx + 0] = (uint8_t)deARGB_getRed(pixel);
179             pixels[4 * ndx + 1] = (uint8_t)deARGB_getGreen(pixel);
180             pixels[4 * ndx + 2] = (uint8_t)deARGB_getBlue(pixel);
181             pixels[4 * ndx + 3] = (uint8_t)deARGB_getAlpha(pixel);
182         }
183 }
184 
deImage_getPixelPtr(const deImage * image)185 void *deImage_getPixelPtr(const deImage *image)
186 {
187     return image->pixels;
188 }
189 
deImage_getWidth(const deImage * image)190 int deImage_getWidth(const deImage *image)
191 {
192     return image->width;
193 }
194 
deImage_getHeight(const deImage * image)195 int deImage_getHeight(const deImage *image)
196 {
197     return image->height;
198 }
199