NetSurf
bitmap.c
Go to the documentation of this file.
1/*
2 * Copyright 2022 Michael Drake <tlsa@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/** \file
20 * Internal core bitmap interface.
21 */
22
23#include <stddef.h>
24#include <stdint.h>
25#include <stdbool.h>
26
27#include "utils/log.h"
28#include "utils/errors.h"
29
30#include "desktop/bitmap.h"
32
33/** The client bitmap format. */
35
36/** The client bitmap colour channel layout. */
38 .r = 0,
39 .g = 1,
40 .b = 2,
41 .a = 3,
42};
43
44/**
45 * Get the colour layout for the given bitmap format.
46 *
47 * \param[in] fmt Pixel format to get channel layout for,
48 * \return channel layout structure.
49 */
51 const bitmap_fmt_t *fmt)
52{
53 switch (fmt->layout) {
54 default:
55 /* Fall through. */
57 return (struct bitmap_colour_layout) {
58 .r = 0,
59 .g = 1,
60 .b = 2,
61 .a = 3,
62 };
63
65 return (struct bitmap_colour_layout) {
66 .b = 0,
67 .g = 1,
68 .r = 2,
69 .a = 3,
70 };
71
73 return (struct bitmap_colour_layout) {
74 .a = 0,
75 .r = 1,
76 .g = 2,
77 .b = 3,
78 };
79
81 return (struct bitmap_colour_layout) {
82 .a = 0,
83 .b = 1,
84 .g = 2,
85 .r = 3,
86 };
87 }
88}
89
90/**
91 * Get string for given pixel layout.
92 *
93 * \param[in] layout The pixel layout to get string for,
94 * \return String for given layout.
95 */
96static const char *bitmap__layout_to_str(enum bitmap_layout layout)
97{
98 const char *const str[] = {
99 [BITMAP_LAYOUT_R8G8B8A8] = "Byte-wise RGBA",
100 [BITMAP_LAYOUT_B8G8R8A8] = "Byte-wise BGRA",
101 [BITMAP_LAYOUT_A8R8G8B8] = "Byte-wise ARGB",
102 [BITMAP_LAYOUT_A8B8G8R8] = "Byte-wise ABGR",
103 [BITMAP_LAYOUT_RGBA8888] = "0xRRGGBBAA (native endian)",
104 [BITMAP_LAYOUT_BGRA8888] = "0xBBGGRRAA (native endian)",
105 [BITMAP_LAYOUT_ARGB8888] = "0xAARRGGBB (native endian)",
106 [BITMAP_LAYOUT_ABGR8888] = "0xAABBGGRR (native endian)",
107 };
108
109 if ((size_t)layout >= (sizeof(str)) / sizeof(*str) ||
110 str[layout] == NULL) {
111 return "Unknown";
112 }
113
114 return str[layout];
115}
116
117/* Exported function, documented in include/netsurf/bitmap.h */
118void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
119{
120 bitmap_fmt = *bitmap_format;
121
122 NSLOG(netsurf, INFO, "Setting core bitmap format to: %s%s",
123 bitmap__layout_to_str(bitmap_format->layout),
124 bitmap_format->pma ? " pre multiplied alpha" : "");
125
127
128 if (bitmap_format->layout != bitmap_fmt.layout) {
129 NSLOG(netsurf, INFO, "Sanitised layout to: %s",
131 }
132
134}
135
136/**
137 * Swap colour component order.
138 *
139 * \param[in] width Bitmap width in pixels.
140 * \param[in] height Bitmap height in pixels.
141 * \param[in] buffer Pixel buffer.
142 * \param[in] rowstride Pixel buffer row stride in bytes.
143 * \param[in] to Pixel layout to convert to.
144 * \param[in] from Pixel layout to convert from.
145 */
146static inline void bitmap__format_convert(
147 int width,
148 int height,
149 uint8_t *buffer,
150 size_t rowstride,
153{
154 /* Just swapping the components around */
155 for (int y = 0; y < height; y++) {
156 uint8_t *row = buffer;
157
158 for (int x = 0; x < width; x++) {
159 const uint32_t px = *((uint32_t *)(void *) row);
160
161 row[to.r] = ((const uint8_t *) &px)[from.r];
162 row[to.g] = ((const uint8_t *) &px)[from.g];
163 row[to.b] = ((const uint8_t *) &px)[from.b];
164 row[to.a] = ((const uint8_t *) &px)[from.a];
165
166 row += sizeof(uint32_t);
167 }
168
169 buffer += rowstride;
170 }
171}
172
173/**
174 * Convert plain alpha to premultiplied alpha.
175 *
176 * \param[in] width Bitmap width in pixels.
177 * \param[in] height Bitmap height in pixels.
178 * \param[in] buffer Pixel buffer.
179 * \param[in] rowstride Pixel buffer row stride in bytes.
180 * \param[in] to Pixel layout to convert to.
181 * \param[in] from Pixel layout to convert from.
182 */
184 int width,
185 int height,
186 uint8_t *buffer,
187 size_t rowstride,
190{
191 for (int y = 0; y < height; y++) {
192 uint8_t *row = buffer;
193
194 for (int x = 0; x < width; x++) {
195 const uint32_t px = *((uint32_t *)(void *) row);
196 uint32_t a, r, g, b;
197
198 r = ((const uint8_t *) &px)[from.r];
199 g = ((const uint8_t *) &px)[from.g];
200 b = ((const uint8_t *) &px)[from.b];
201 a = ((const uint8_t *) &px)[from.a];
202
203 if (a != 0) {
204 r = ((r * (a + 1)) >> 8) & 0xff;
205 g = ((g * (a + 1)) >> 8) & 0xff;
206 b = ((b * (a + 1)) >> 8) & 0xff;
207 } else {
208 r = g = b = 0;
209 }
210
211 row[to.r] = r;
212 row[to.g] = g;
213 row[to.b] = b;
214 row[to.a] = a;
215
216 row += sizeof(uint32_t);
217 }
218
219 buffer += rowstride;
220 }
221}
222
223/**
224 * Convert from premultiplied alpha to plain alpha.
225 *
226 * \param[in] width Bitmap width in pixels.
227 * \param[in] height Bitmap height in pixels.
228 * \param[in] buffer Pixel buffer.
229 * \param[in] rowstride Pixel buffer row stride in bytes.
230 * \param[in] to Pixel layout to convert to.
231 * \param[in] from Pixel layout to convert from.
232 */
234 int width,
235 int height,
236 uint8_t *buffer,
237 size_t rowstride,
240{
241 for (int y = 0; y < height; y++) {
242 uint8_t *row = buffer;
243
244 for (int x = 0; x < width; x++) {
245 const uint32_t px = *((uint32_t *)(void *) row);
246 uint32_t a, r, g, b;
247
248 r = ((const uint8_t *) &px)[from.r];
249 g = ((const uint8_t *) &px)[from.g];
250 b = ((const uint8_t *) &px)[from.b];
251 a = ((const uint8_t *) &px)[from.a];
252
253 if (a != 0) {
254 r = (r << 8) / a;
255 g = (g << 8) / a;
256 b = (b << 8) / a;
257
258 r = (r > 255) ? 255 : r;
259 g = (g > 255) ? 255 : g;
260 b = (b > 255) ? 255 : b;
261 } else {
262 r = g = b = 0;
263 }
264
265 row[to.r] = r;
266 row[to.g] = g;
267 row[to.b] = b;
268 row[to.a] = a;
269
270 row += sizeof(uint32_t);
271 }
272
273 buffer += rowstride;
274 }
275}
276
277/* Exported function, documented in desktop/bitmap.h */
279 const bitmap_fmt_t *fmt_from,
280 const bitmap_fmt_t *fmt_to)
281{
284 bool opaque = guit->bitmap->get_opaque(bitmap);
285 uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
286 size_t rowstride = guit->bitmap->get_rowstride(bitmap);
289
290 NSLOG(netsurf, DEEPDEBUG, "%p: format conversion (%u%s --> %u%s)",
291 bitmap,
292 fmt_from->layout, fmt_from->pma ? " pma" : "",
293 fmt_to->layout, fmt_to->pma ? " pma" : "");
294
295 if (fmt_from->pma == fmt_to->pma) {
296 /* Just component order to switch. */
299 rowstride, to, from);
300
301 } else if (opaque == false) {
302 /* Need to do conversion to/from premultiplied alpha. */
303 if (fmt_to->pma) {
306 rowstride, to, from);
307 } else {
310 rowstride, to, from);
311 }
312 }
313}
314
315/* Exported function, documented in desktop/bitmap.h */
317{
320 size_t rowstride = guit->bitmap->get_rowstride(bitmap);
321 const uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
322
323 width *= sizeof(uint32_t);
324
325 for (int y = 0; y < height; y++) {
326 const uint8_t *row = buffer;
327
328 for (int x = bitmap_layout.a; x < width; x += 4) {
329 if (row[x] != 0xff) {
330 return false;
331 }
332 }
333
334 buffer += rowstride;
335 }
336
337 return true;
338}
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
static const char * bitmap__layout_to_str(enum bitmap_layout layout)
Get string for given pixel layout.
Definition: bitmap.c:96
static void bitmap__format_convert_from_pma(int width, int height, uint8_t *buffer, size_t rowstride, struct bitmap_colour_layout to, struct bitmap_colour_layout from)
Convert from premultiplied alpha to plain alpha.
Definition: bitmap.c:233
bool bitmap_test_opaque(void *bitmap)
Test whether a bitmap is completely opaque (no transparency).
Definition: bitmap.c:316
static void bitmap__format_convert(int width, int height, uint8_t *buffer, size_t rowstride, struct bitmap_colour_layout to, struct bitmap_colour_layout from)
Swap colour component order.
Definition: bitmap.c:146
bitmap_fmt_t bitmap_fmt
The client bitmap format.
Definition: bitmap.c:34
void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
Set client bitmap format.
Definition: bitmap.c:118
static struct bitmap_colour_layout bitmap__get_colour_layout(const bitmap_fmt_t *fmt)
Get the colour layout for the given bitmap format.
Definition: bitmap.c:50
static void bitmap__format_convert_to_pma(int width, int height, uint8_t *buffer, size_t rowstride, struct bitmap_colour_layout to, struct bitmap_colour_layout from)
Convert plain alpha to premultiplied alpha.
Definition: bitmap.c:183
void bitmap_format_convert(void *bitmap, const bitmap_fmt_t *fmt_from, const bitmap_fmt_t *fmt_to)
Convert bitmap from one format to another.
Definition: bitmap.c:278
Internal core bitmap interface.
static enum bitmap_layout bitmap_sanitise_bitmap_layout(enum bitmap_layout layout)
Sanitise bitmap pixel component layout.
Definition: bitmap.h:69
Error codes.
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:50
Interface to core interface table.
bitmap_layout
NetSurf bitmap pixel layout.
Definition: bitmap.h:48
@ BITMAP_LAYOUT_ABGR8888
32-bit BGRA (0xAABBGGRR).
Definition: bitmap.h:91
@ BITMAP_LAYOUT_BGRA8888
32-bit BGRA (0xBBGGRRAA).
Definition: bitmap.h:75
@ BITMAP_LAYOUT_ARGB8888
32-bit ARGB (0xAARRGGBB).
Definition: bitmap.h:83
@ BITMAP_LAYOUT_B8G8R8A8
Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA.
Definition: bitmap.h:53
@ BITMAP_LAYOUT_R8G8B8A8
Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA.
Definition: bitmap.h:50
@ BITMAP_LAYOUT_A8B8G8R8
Bite-wise ABGR: Byte order: 0xAA, 0xBB, 0xGG, 0xRR.
Definition: bitmap.h:59
@ BITMAP_LAYOUT_A8R8G8B8
Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB.
Definition: bitmap.h:56
@ BITMAP_LAYOUT_RGBA8888
32-bit RGBA (0xRRGGBBAA).
Definition: bitmap.h:67
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int width
Definition: gui.c:160
int height
Definition: gui.c:161
Pixel format: colour component order.
Definition: bitmap.h:32
uint8_t g
Byte offset within pixel to green component.
Definition: bitmap.h:34
uint8_t b
Byte offset within pixel to blue component.
Definition: bitmap.h:35
uint8_t a
Byte offset within pixel to alpha component.
Definition: bitmap.h:36
uint8_t r
Byte offset within pixel to red component.
Definition: bitmap.h:33
Bitmap format specifier.
Definition: bitmap.h:95
bool pma
Premultiplied alpha.
Definition: bitmap.h:97
enum bitmap_layout layout
Colour component layout.
Definition: bitmap.h:96
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
int(* get_height)(void *bitmap)
Get the bitmap height.
Definition: bitmap.h:193
int(* get_width)(void *bitmap)
Get the bitmap width.
Definition: bitmap.h:185
size_t(* get_rowstride)(void *bitmap)
Get the number of bytes per row of the image.
Definition: bitmap.h:177
bool(* get_opaque)(void *bitmap)
Get the opacity of a bitmap.
Definition: bitmap.h:159
unsigned char *(* get_buffer)(void *bitmap)
Get the image buffer from a bitmap.
Definition: bitmap.h:169
struct gui_bitmap_table * bitmap
Bitmap table.
Definition: gui_table.h:153
char from[32]
Encoding name to convert from.
Definition: utf8.c:143
char to[32]
Encoding name to convert to.
Definition: utf8.c:144