Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/io/image.cpp
20778 views
1
/**************************************************************************/
2
/* image.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "image.h"
32
33
#include "core/config/project_settings.h"
34
#include "core/error/error_macros.h"
35
#include "core/io/image_loader.h"
36
#include "core/io/resource_loader.h"
37
#include "core/math/math_funcs.h"
38
#include "core/templates/hash_map.h"
39
#include "core/variant/dictionary.h"
40
41
const char *Image::format_names[Image::FORMAT_MAX] = {
42
"Lum8",
43
"LumAlpha8",
44
"Red8",
45
"RedGreen",
46
"RGB8",
47
"RGBA8",
48
"RGBA4444",
49
"RGBA5551", // Actually RGB565, kept as RGBA5551 for compatibility.
50
"RFloat",
51
"RGFloat",
52
"RGBFloat",
53
"RGBAFloat",
54
"RHalf",
55
"RGHalf",
56
"RGBHalf",
57
"RGBAHalf",
58
"RGBE9995",
59
"DXT1 RGB8",
60
"DXT3 RGBA8",
61
"DXT5 RGBA8",
62
"RGTC Red8",
63
"RGTC RedGreen8",
64
"BPTC_RGBA",
65
"BPTC_RGBF",
66
"BPTC_RGBFU",
67
"ETC",
68
"ETC2_R11",
69
"ETC2_R11S",
70
"ETC2_RG11",
71
"ETC2_RG11S",
72
"ETC2_RGB8",
73
"ETC2_RGBA8",
74
"ETC2_RGB8A1",
75
"ETC2_RA_AS_RG",
76
"FORMAT_DXT5_RA_AS_RG",
77
"ASTC_4x4",
78
"ASTC_4x4_HDR",
79
"ASTC_8x8",
80
"ASTC_8x8_HDR",
81
"R16",
82
"RG16",
83
"RGB16",
84
"RGBA16",
85
"R16Int",
86
"RG16Int",
87
"RGB16Int",
88
"RGBA16Int",
89
};
90
91
// External VRAM compression function pointers.
92
93
void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
94
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr;
95
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
96
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
97
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
98
99
Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr;
100
Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr;
101
102
// External VRAM decompression function pointers.
103
104
void (*Image::_image_decompress_bc)(Image *) = nullptr;
105
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
106
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
107
void (*Image::_image_decompress_etc2)(Image *) = nullptr;
108
void (*Image::_image_decompress_astc)(Image *) = nullptr;
109
110
// External packer function pointers.
111
112
Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr;
113
Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr;
114
Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr;
115
Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels, const BasisUniversalPackerParams &) = nullptr;
116
117
Ref<Image> (*Image::webp_unpacker)(const Vector<uint8_t> &) = nullptr;
118
Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr;
119
Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr;
120
Ref<Image> (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr;
121
122
void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) {
123
uint32_t ofs = (p_y * width + p_x) * p_pixel_size;
124
memcpy(p_data + ofs, p_pixel, p_pixel_size);
125
}
126
127
void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel) {
128
uint32_t ofs = (p_y * width + p_x) * p_pixel_size;
129
memcpy(p_pixel, p_data + ofs, p_pixel_size);
130
}
131
132
int Image::get_format_pixel_size(Format p_format) {
133
switch (p_format) {
134
case FORMAT_L8:
135
return 1;
136
case FORMAT_LA8:
137
return 2;
138
case FORMAT_R8:
139
return 1;
140
case FORMAT_RG8:
141
return 2;
142
case FORMAT_RGB8:
143
return 3;
144
case FORMAT_RGBA8:
145
return 4;
146
case FORMAT_RGBA4444:
147
return 2;
148
case FORMAT_RGB565:
149
return 2;
150
case FORMAT_RF:
151
return 4;
152
case FORMAT_RGF:
153
return 8;
154
case FORMAT_RGBF:
155
return 12;
156
case FORMAT_RGBAF:
157
return 16;
158
case FORMAT_RH:
159
return 2;
160
case FORMAT_RGH:
161
return 4;
162
case FORMAT_RGBH:
163
return 6;
164
case FORMAT_RGBAH:
165
return 8;
166
case FORMAT_RGBE9995:
167
return 4;
168
case FORMAT_DXT1:
169
return 1;
170
case FORMAT_DXT3:
171
return 1;
172
case FORMAT_DXT5:
173
return 1;
174
case FORMAT_RGTC_R:
175
return 1;
176
case FORMAT_RGTC_RG:
177
return 1;
178
case FORMAT_BPTC_RGBA:
179
return 1;
180
case FORMAT_BPTC_RGBF:
181
return 1;
182
case FORMAT_BPTC_RGBFU:
183
return 1;
184
case FORMAT_ETC:
185
return 1;
186
case FORMAT_ETC2_R11:
187
return 1;
188
case FORMAT_ETC2_R11S:
189
return 1;
190
case FORMAT_ETC2_RG11:
191
return 1;
192
case FORMAT_ETC2_RG11S:
193
return 1;
194
case FORMAT_ETC2_RGB8:
195
return 1;
196
case FORMAT_ETC2_RGBA8:
197
return 1;
198
case FORMAT_ETC2_RGB8A1:
199
return 1;
200
case FORMAT_ETC2_RA_AS_RG:
201
return 1;
202
case FORMAT_DXT5_RA_AS_RG:
203
return 1;
204
case FORMAT_ASTC_4x4:
205
return 1;
206
case FORMAT_ASTC_4x4_HDR:
207
return 1;
208
case FORMAT_ASTC_8x8:
209
return 1;
210
case FORMAT_ASTC_8x8_HDR:
211
return 1;
212
case FORMAT_R16:
213
return 2;
214
case FORMAT_RG16:
215
return 4;
216
case FORMAT_RGB16:
217
return 6;
218
case FORMAT_RGBA16:
219
return 8;
220
case FORMAT_R16I:
221
return 2;
222
case FORMAT_RG16I:
223
return 4;
224
case FORMAT_RGB16I:
225
return 6;
226
case FORMAT_RGBA16I:
227
return 8;
228
case FORMAT_MAX: {
229
}
230
}
231
return 0;
232
}
233
234
void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
235
switch (p_format) {
236
case FORMAT_DXT1:
237
case FORMAT_DXT3:
238
case FORMAT_DXT5:
239
case FORMAT_RGTC_R:
240
case FORMAT_RGTC_RG: {
241
r_w = 4;
242
r_h = 4;
243
} break;
244
case FORMAT_ETC: {
245
r_w = 4;
246
r_h = 4;
247
} break;
248
case FORMAT_BPTC_RGBA:
249
case FORMAT_BPTC_RGBF:
250
case FORMAT_BPTC_RGBFU: {
251
r_w = 4;
252
r_h = 4;
253
} break;
254
case FORMAT_ETC2_R11:
255
case FORMAT_ETC2_R11S:
256
case FORMAT_ETC2_RG11:
257
case FORMAT_ETC2_RG11S:
258
case FORMAT_ETC2_RGB8:
259
case FORMAT_ETC2_RGBA8:
260
case FORMAT_ETC2_RGB8A1:
261
case FORMAT_ETC2_RA_AS_RG:
262
case FORMAT_DXT5_RA_AS_RG: {
263
r_w = 4;
264
r_h = 4;
265
} break;
266
case FORMAT_ASTC_4x4:
267
case FORMAT_ASTC_4x4_HDR: {
268
r_w = 4;
269
r_h = 4;
270
} break;
271
case FORMAT_ASTC_8x8:
272
case FORMAT_ASTC_8x8_HDR: {
273
r_w = 8;
274
r_h = 8;
275
} break;
276
default: {
277
r_w = 1;
278
r_h = 1;
279
} break;
280
}
281
}
282
283
int Image::get_format_pixel_rshift(Format p_format) {
284
if (p_format == FORMAT_ASTC_8x8) {
285
return 2;
286
} else if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
287
return 1;
288
} else {
289
return 0;
290
}
291
}
292
293
int Image::get_format_block_size(Format p_format) {
294
switch (p_format) {
295
case FORMAT_DXT1:
296
case FORMAT_DXT3:
297
case FORMAT_DXT5:
298
case FORMAT_RGTC_R:
299
case FORMAT_RGTC_RG: {
300
return 4;
301
}
302
case FORMAT_ETC: {
303
return 4;
304
}
305
case FORMAT_BPTC_RGBA:
306
case FORMAT_BPTC_RGBF:
307
case FORMAT_BPTC_RGBFU: {
308
return 4;
309
}
310
case FORMAT_ETC2_R11:
311
case FORMAT_ETC2_R11S:
312
case FORMAT_ETC2_RG11:
313
case FORMAT_ETC2_RG11S:
314
case FORMAT_ETC2_RGB8:
315
case FORMAT_ETC2_RGBA8:
316
case FORMAT_ETC2_RGB8A1:
317
case FORMAT_ETC2_RA_AS_RG:
318
case FORMAT_DXT5_RA_AS_RG: {
319
return 4;
320
}
321
case FORMAT_ASTC_4x4:
322
case FORMAT_ASTC_4x4_HDR: {
323
return 4;
324
}
325
case FORMAT_ASTC_8x8:
326
case FORMAT_ASTC_8x8_HDR: {
327
return 8;
328
}
329
default: {
330
}
331
}
332
333
return 1;
334
}
335
336
void Image::_get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const {
337
int w = width;
338
int h = height;
339
int64_t ofs = 0;
340
341
int pixel_size = get_format_pixel_size(format);
342
int pixel_rshift = get_format_pixel_rshift(format);
343
int block = get_format_block_size(format);
344
int minw, minh;
345
get_format_min_pixel_size(format, minw, minh);
346
347
for (int i = 0; i < p_mipmap; i++) {
348
int bw = w % block != 0 ? w + (block - w % block) : w;
349
int bh = h % block != 0 ? h + (block - h % block) : h;
350
351
int64_t s = bw * bh;
352
353
s *= pixel_size;
354
s >>= pixel_rshift;
355
ofs += s;
356
w = MAX(minw, w >> 1);
357
h = MAX(minh, h >> 1);
358
}
359
360
r_offset = ofs;
361
r_width = w;
362
r_height = h;
363
}
364
365
int64_t Image::get_mipmap_offset(int p_mipmap) const {
366
ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1);
367
368
int64_t ofs;
369
int w, h;
370
_get_mipmap_offset_and_size(p_mipmap, ofs, w, h);
371
return ofs;
372
}
373
374
void Image::get_mipmap_offset_and_size(int p_mipmap, int64_t &r_ofs, int64_t &r_size) const {
375
int64_t ofs;
376
int w, h;
377
_get_mipmap_offset_and_size(p_mipmap, ofs, w, h);
378
int64_t ofs2;
379
_get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w, h);
380
r_ofs = ofs;
381
r_size = ofs2 - ofs;
382
}
383
384
void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int64_t &r_ofs, int64_t &r_size, int &w, int &h) const {
385
int64_t ofs;
386
_get_mipmap_offset_and_size(p_mipmap, ofs, w, h);
387
int64_t ofs2;
388
int w2, h2;
389
_get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w2, h2);
390
r_ofs = ofs;
391
r_size = ofs2 - ofs;
392
}
393
394
Image::Image3DValidateError Image::validate_3d_image(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_images) {
395
int w = p_width;
396
int h = p_height;
397
int d = p_depth;
398
399
int arr_ofs = 0;
400
401
while (true) {
402
for (int i = 0; i < d; i++) {
403
int idx = i + arr_ofs;
404
if (idx >= p_images.size()) {
405
return VALIDATE_3D_ERR_MISSING_IMAGES;
406
}
407
if (p_images[idx].is_null() || p_images[idx]->is_empty()) {
408
return VALIDATE_3D_ERR_IMAGE_EMPTY;
409
}
410
if (p_images[idx]->get_format() != p_format) {
411
return VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH;
412
}
413
if (p_images[idx]->get_width() != w || p_images[idx]->get_height() != h) {
414
return VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH;
415
}
416
if (p_images[idx]->has_mipmaps()) {
417
return VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS;
418
}
419
}
420
421
arr_ofs += d;
422
423
if (!p_mipmaps) {
424
break;
425
}
426
427
if (w == 1 && h == 1 && d == 1) {
428
break;
429
}
430
431
w = MAX(1, w >> 1);
432
h = MAX(1, h >> 1);
433
d = MAX(1, d >> 1);
434
}
435
436
if (arr_ofs != p_images.size()) {
437
return VALIDATE_3D_ERR_EXTRA_IMAGES;
438
}
439
440
return VALIDATE_3D_OK;
441
}
442
443
String Image::get_3d_image_validation_error_text(Image3DValidateError p_error) {
444
switch (p_error) {
445
case VALIDATE_3D_OK: {
446
return "Ok";
447
} break;
448
case VALIDATE_3D_ERR_IMAGE_EMPTY: {
449
return "Empty Image found";
450
} break;
451
case VALIDATE_3D_ERR_MISSING_IMAGES: {
452
return "Missing Images";
453
} break;
454
case VALIDATE_3D_ERR_EXTRA_IMAGES: {
455
return "Too many Images";
456
} break;
457
case VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH: {
458
return "Image size mismatch";
459
} break;
460
case VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH: {
461
return "Image format mismatch";
462
} break;
463
case VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS: {
464
return "Image has included mipmaps";
465
} break;
466
}
467
return String();
468
}
469
470
int Image::get_width() const {
471
return width;
472
}
473
474
int Image::get_height() const {
475
return height;
476
}
477
478
Size2i Image::get_size() const {
479
return Size2i(width, height);
480
}
481
482
bool Image::has_mipmaps() const {
483
return mipmaps;
484
}
485
486
int Image::get_mipmap_count() const {
487
if (mipmaps) {
488
return get_image_required_mipmaps(width, height, format);
489
} else {
490
return 0;
491
}
492
}
493
494
// Using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers.
495
template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray>
496
static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) {
497
constexpr uint32_t max_bytes = MAX(read_bytes, write_bytes);
498
499
for (int y = 0; y < p_height; y++) {
500
for (int x = 0; x < p_width; x++) {
501
const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))];
502
uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))];
503
504
uint8_t rgba[4] = { 0, 0, 0, 255 };
505
506
if constexpr (read_gray) {
507
rgba[0] = rofs[0];
508
rgba[1] = rofs[0];
509
rgba[2] = rofs[0];
510
} else {
511
for (uint32_t i = 0; i < max_bytes; i++) {
512
rgba[i] = (i < read_bytes) ? rofs[i] : 0;
513
}
514
}
515
516
if constexpr (read_alpha || write_alpha) {
517
rgba[3] = read_alpha ? rofs[read_bytes] : 255;
518
}
519
520
if constexpr (write_gray) {
521
// REC.709
522
const uint8_t luminance = (13938U * rgba[0] + 46869U * rgba[1] + 4729U * rgba[2] + 32768U) >> 16U;
523
wofs[0] = luminance;
524
} else {
525
for (uint32_t i = 0; i < write_bytes; i++) {
526
wofs[i] = rgba[i];
527
}
528
}
529
530
if constexpr (write_alpha) {
531
wofs[write_bytes] = rgba[3];
532
}
533
}
534
}
535
}
536
537
template <typename T, uint32_t read_channels, uint32_t write_channels, T def_zero, T def_one>
538
static void _convert_fast(int p_width, int p_height, const T *p_src, T *p_dst) {
539
uint32_t dst_count = 0;
540
uint32_t src_count = 0;
541
542
const int resolution = p_width * p_height;
543
544
for (int i = 0; i < resolution; i++) {
545
memcpy(p_dst + dst_count, p_src + src_count, MIN(read_channels, write_channels) * sizeof(T));
546
547
if constexpr (write_channels > read_channels) {
548
const T def_value[4] = { def_zero, def_zero, def_zero, def_one };
549
memcpy(p_dst + dst_count + read_channels, &def_value[read_channels], (write_channels - read_channels) * sizeof(T));
550
}
551
552
dst_count += write_channels;
553
src_count += read_channels;
554
}
555
}
556
557
static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_format1) {
558
if (p_format0 <= Image::FORMAT_RGBA8 && p_format1 <= Image::FORMAT_RGBA8) {
559
return true;
560
} else if (p_format0 <= Image::FORMAT_RGBAH && p_format0 >= Image::FORMAT_RH && p_format1 <= Image::FORMAT_RGBAH && p_format1 >= Image::FORMAT_RH) {
561
return true;
562
} else if (p_format0 <= Image::FORMAT_RGBAF && p_format0 >= Image::FORMAT_RF && p_format1 <= Image::FORMAT_RGBAF && p_format1 >= Image::FORMAT_RF) {
563
return true;
564
}
565
566
return false;
567
}
568
569
void Image::convert(Format p_new_format) {
570
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format));
571
ERR_FAIL_COND_MSG(Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format),
572
"Cannot convert to (or from) compressed formats. Use compress() and decompress() instead.");
573
574
if (data.is_empty() || p_new_format == format) {
575
return;
576
}
577
578
// Includes the main image.
579
const int mipmap_count = get_mipmap_count() + 1;
580
581
if (!_are_formats_compatible(format, p_new_format)) {
582
// Use put/set pixel which is slower but works with non-byte formats.
583
Image new_img(width, height, mipmaps, p_new_format);
584
585
for (int mip = 0; mip < mipmap_count; mip++) {
586
int64_t src_mip_ofs, dst_mip_ofs;
587
int w, h;
588
_get_mipmap_offset_and_size(mip, src_mip_ofs, w, h);
589
new_img._get_mipmap_offset_and_size(mip, dst_mip_ofs, w, h);
590
591
uint8_t *dst_mip_ptr = new_img.ptrw() + dst_mip_ofs;
592
const uint8_t *src_mip_ptr = ptr() + src_mip_ofs;
593
594
for (int y = 0; y < h; y++) {
595
for (int x = 0; x < w; x++) {
596
uint32_t mip_ofs = y * w + x;
597
new_img._set_color_at_ofs(dst_mip_ptr, mip_ofs, _get_color_at_ofs(src_mip_ptr, mip_ofs));
598
}
599
}
600
}
601
602
_copy_internals_from(new_img);
603
return;
604
}
605
606
// Convert the formats in an optimized way by removing/adding color channels if necessary.
607
Image new_img(width, height, mipmaps, p_new_format);
608
609
const int conversion_type = format | p_new_format << 8;
610
611
for (int mip = 0; mip < mipmap_count; mip++) {
612
int64_t mip_offset = 0;
613
int64_t mip_size = 0;
614
int mip_width = 0;
615
int mip_height = 0;
616
get_mipmap_offset_size_and_dimensions(mip, mip_offset, mip_size, mip_width, mip_height);
617
618
const uint8_t *rptr = data.ptr() + mip_offset;
619
uint8_t *wptr = new_img.data.ptrw() + new_img.get_mipmap_offset(mip);
620
621
switch (conversion_type) {
622
case FORMAT_L8 | (FORMAT_LA8 << 8):
623
_convert<1, false, 1, true, true, true>(mip_width, mip_height, rptr, wptr);
624
break;
625
case FORMAT_L8 | (FORMAT_R8 << 8):
626
_convert<1, false, 1, false, true, false>(mip_width, mip_height, rptr, wptr);
627
break;
628
case FORMAT_L8 | (FORMAT_RG8 << 8):
629
_convert<1, false, 2, false, true, false>(mip_width, mip_height, rptr, wptr);
630
break;
631
case FORMAT_L8 | (FORMAT_RGB8 << 8):
632
_convert<1, false, 3, false, true, false>(mip_width, mip_height, rptr, wptr);
633
break;
634
case FORMAT_L8 | (FORMAT_RGBA8 << 8):
635
_convert<1, false, 3, true, true, false>(mip_width, mip_height, rptr, wptr);
636
break;
637
case FORMAT_LA8 | (FORMAT_L8 << 8):
638
_convert<1, true, 1, false, true, true>(mip_width, mip_height, rptr, wptr);
639
break;
640
case FORMAT_LA8 | (FORMAT_R8 << 8):
641
_convert<1, true, 1, false, true, false>(mip_width, mip_height, rptr, wptr);
642
break;
643
case FORMAT_LA8 | (FORMAT_RG8 << 8):
644
_convert<1, true, 2, false, true, false>(mip_width, mip_height, rptr, wptr);
645
break;
646
case FORMAT_LA8 | (FORMAT_RGB8 << 8):
647
_convert<1, true, 3, false, true, false>(mip_width, mip_height, rptr, wptr);
648
break;
649
case FORMAT_LA8 | (FORMAT_RGBA8 << 8):
650
_convert<1, true, 3, true, true, false>(mip_width, mip_height, rptr, wptr);
651
break;
652
case FORMAT_R8 | (FORMAT_L8 << 8):
653
_convert<1, false, 1, false, false, true>(mip_width, mip_height, rptr, wptr);
654
break;
655
case FORMAT_R8 | (FORMAT_LA8 << 8):
656
_convert<1, false, 1, true, false, true>(mip_width, mip_height, rptr, wptr);
657
break;
658
case FORMAT_R8 | (FORMAT_RG8 << 8):
659
_convert<1, false, 2, false, false, false>(mip_width, mip_height, rptr, wptr);
660
break;
661
case FORMAT_R8 | (FORMAT_RGB8 << 8):
662
_convert<1, false, 3, false, false, false>(mip_width, mip_height, rptr, wptr);
663
break;
664
case FORMAT_R8 | (FORMAT_RGBA8 << 8):
665
_convert<1, false, 3, true, false, false>(mip_width, mip_height, rptr, wptr);
666
break;
667
case FORMAT_RG8 | (FORMAT_L8 << 8):
668
_convert<2, false, 1, false, false, true>(mip_width, mip_height, rptr, wptr);
669
break;
670
case FORMAT_RG8 | (FORMAT_LA8 << 8):
671
_convert<2, false, 1, true, false, true>(mip_width, mip_height, rptr, wptr);
672
break;
673
case FORMAT_RG8 | (FORMAT_R8 << 8):
674
_convert<2, false, 1, false, false, false>(mip_width, mip_height, rptr, wptr);
675
break;
676
case FORMAT_RG8 | (FORMAT_RGB8 << 8):
677
_convert<2, false, 3, false, false, false>(mip_width, mip_height, rptr, wptr);
678
break;
679
case FORMAT_RG8 | (FORMAT_RGBA8 << 8):
680
_convert<2, false, 3, true, false, false>(mip_width, mip_height, rptr, wptr);
681
break;
682
case FORMAT_RGB8 | (FORMAT_L8 << 8):
683
_convert<3, false, 1, false, false, true>(mip_width, mip_height, rptr, wptr);
684
break;
685
case FORMAT_RGB8 | (FORMAT_LA8 << 8):
686
_convert<3, false, 1, true, false, true>(mip_width, mip_height, rptr, wptr);
687
break;
688
case FORMAT_RGB8 | (FORMAT_R8 << 8):
689
_convert<3, false, 1, false, false, false>(mip_width, mip_height, rptr, wptr);
690
break;
691
case FORMAT_RGB8 | (FORMAT_RG8 << 8):
692
_convert<3, false, 2, false, false, false>(mip_width, mip_height, rptr, wptr);
693
break;
694
case FORMAT_RGB8 | (FORMAT_RGBA8 << 8):
695
_convert<3, false, 3, true, false, false>(mip_width, mip_height, rptr, wptr);
696
break;
697
case FORMAT_RGBA8 | (FORMAT_L8 << 8):
698
_convert<3, true, 1, false, false, true>(mip_width, mip_height, rptr, wptr);
699
break;
700
case FORMAT_RGBA8 | (FORMAT_LA8 << 8):
701
_convert<3, true, 1, true, false, true>(mip_width, mip_height, rptr, wptr);
702
break;
703
case FORMAT_RGBA8 | (FORMAT_R8 << 8):
704
_convert<3, true, 1, false, false, false>(mip_width, mip_height, rptr, wptr);
705
break;
706
case FORMAT_RGBA8 | (FORMAT_RG8 << 8):
707
_convert<3, true, 2, false, false, false>(mip_width, mip_height, rptr, wptr);
708
break;
709
case FORMAT_RGBA8 | (FORMAT_RGB8 << 8):
710
_convert<3, true, 3, false, false, false>(mip_width, mip_height, rptr, wptr);
711
break;
712
case FORMAT_RH | (FORMAT_RGH << 8):
713
_convert_fast<uint16_t, 1, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
714
break;
715
case FORMAT_RH | (FORMAT_RGBH << 8):
716
_convert_fast<uint16_t, 1, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
717
break;
718
case FORMAT_RH | (FORMAT_RGBAH << 8):
719
_convert_fast<uint16_t, 1, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
720
break;
721
case FORMAT_RGH | (FORMAT_RH << 8):
722
_convert_fast<uint16_t, 2, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
723
break;
724
case FORMAT_RGH | (FORMAT_RGBH << 8):
725
_convert_fast<uint16_t, 2, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
726
break;
727
case FORMAT_RGH | (FORMAT_RGBAH << 8):
728
_convert_fast<uint16_t, 2, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
729
break;
730
case FORMAT_RGBH | (FORMAT_RH << 8):
731
_convert_fast<uint16_t, 3, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
732
break;
733
case FORMAT_RGBH | (FORMAT_RGH << 8):
734
_convert_fast<uint16_t, 3, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
735
break;
736
case FORMAT_RGBH | (FORMAT_RGBAH << 8):
737
_convert_fast<uint16_t, 3, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
738
break;
739
case FORMAT_RGBAH | (FORMAT_RH << 8):
740
_convert_fast<uint16_t, 4, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
741
break;
742
case FORMAT_RGBAH | (FORMAT_RGH << 8):
743
_convert_fast<uint16_t, 4, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
744
break;
745
case FORMAT_RGBAH | (FORMAT_RGBH << 8):
746
_convert_fast<uint16_t, 4, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
747
break;
748
case FORMAT_RF | (FORMAT_RGF << 8):
749
_convert_fast<uint32_t, 1, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
750
break;
751
case FORMAT_RF | (FORMAT_RGBF << 8):
752
_convert_fast<uint32_t, 1, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
753
break;
754
case FORMAT_RF | (FORMAT_RGBAF << 8):
755
_convert_fast<uint32_t, 1, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
756
break;
757
case FORMAT_RGF | (FORMAT_RF << 8):
758
_convert_fast<uint32_t, 2, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
759
break;
760
case FORMAT_RGF | (FORMAT_RGBF << 8):
761
_convert_fast<uint32_t, 2, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
762
break;
763
case FORMAT_RGF | (FORMAT_RGBAF << 8):
764
_convert_fast<uint32_t, 2, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
765
break;
766
case FORMAT_RGBF | (FORMAT_RF << 8):
767
_convert_fast<uint32_t, 3, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
768
break;
769
case FORMAT_RGBF | (FORMAT_RGF << 8):
770
_convert_fast<uint32_t, 3, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
771
break;
772
case FORMAT_RGBF | (FORMAT_RGBAF << 8):
773
_convert_fast<uint32_t, 3, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
774
break;
775
case FORMAT_RGBAF | (FORMAT_RF << 8):
776
_convert_fast<uint32_t, 4, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
777
break;
778
case FORMAT_RGBAF | (FORMAT_RGF << 8):
779
_convert_fast<uint32_t, 4, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
780
break;
781
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
782
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
783
break;
784
case FORMAT_R16 | (FORMAT_RG16 << 8):
785
_convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
786
break;
787
case FORMAT_R16 | (FORMAT_RGB16 << 8):
788
_convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
789
break;
790
case FORMAT_R16 | (FORMAT_RGBA16 << 8):
791
_convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
792
break;
793
case FORMAT_RG16 | (FORMAT_R16 << 8):
794
_convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
795
break;
796
case FORMAT_RG16 | (FORMAT_RGB16 << 8):
797
_convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
798
break;
799
case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
800
_convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
801
break;
802
case FORMAT_RGB16 | (FORMAT_R16 << 8):
803
_convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
804
break;
805
case FORMAT_RGB16 | (FORMAT_RG16 << 8):
806
_convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
807
break;
808
case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
809
_convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
810
break;
811
case FORMAT_RGBA16 | (FORMAT_R16 << 8):
812
_convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
813
break;
814
case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
815
_convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
816
break;
817
case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
818
_convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
819
break;
820
case FORMAT_R16I | (FORMAT_RG16I << 8):
821
_convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
822
break;
823
case FORMAT_R16I | (FORMAT_RGB16I << 8):
824
_convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
825
break;
826
case FORMAT_R16I | (FORMAT_RGBA16I << 8):
827
_convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
828
break;
829
case FORMAT_RG16I | (FORMAT_R16I << 8):
830
_convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
831
break;
832
case FORMAT_RG16I | (FORMAT_RGB16I << 8):
833
_convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
834
break;
835
case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
836
_convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
837
break;
838
case FORMAT_RGB16I | (FORMAT_R16I << 8):
839
_convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
840
break;
841
case FORMAT_RGB16I | (FORMAT_RG16I << 8):
842
_convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
843
break;
844
case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
845
_convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
846
break;
847
case FORMAT_RGBA16I | (FORMAT_R16I << 8):
848
_convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
849
break;
850
case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
851
_convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
852
break;
853
case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
854
_convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
855
break;
856
}
857
}
858
859
_copy_internals_from(new_img);
860
}
861
862
Image::Format Image::get_format() const {
863
return format;
864
}
865
866
enum ImageScaleType {
867
IMAGE_SCALING_INT,
868
IMAGE_SCALING_FLOAT,
869
};
870
871
static double _bicubic_interp_kernel(double x) {
872
x = Math::abs(x);
873
874
double bc = 0;
875
876
if (x <= 1) {
877
bc = (1.5 * x - 2.5) * x * x + 1;
878
} else if (x < 2) {
879
bc = ((-0.5 * x + 2.5) * x - 4) * x + 2;
880
}
881
882
return bc;
883
}
884
885
template <int CC, typename T, ImageScaleType TYPE>
886
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
887
// get source image size
888
int width = p_src_width;
889
int height = p_src_height;
890
double xfac = (double)width / p_dst_width;
891
double yfac = (double)height / p_dst_height;
892
// coordinates of source points and coefficients
893
double ox, oy, dx, dy;
894
int ox1, oy1, ox2, oy2;
895
// destination pixel values
896
// width and height decreased by 1
897
int ymax = height - 1;
898
int xmax = width - 1;
899
// temporary pointer
900
901
for (uint32_t y = 0; y < p_dst_height; y++) {
902
// Y coordinates
903
oy = (double)(y + 0.5) * yfac - 0.5;
904
oy1 = (int)oy;
905
dy = oy - (double)oy1;
906
907
for (uint32_t x = 0; x < p_dst_width; x++) {
908
// X coordinates
909
ox = (double)(x + 0.5) * xfac - 0.5;
910
ox1 = (int)ox;
911
dx = ox - (double)ox1;
912
913
// initial pixel value
914
915
T *__restrict dst = ((T *)p_dst) + (y * p_dst_width + x) * CC;
916
917
double color[CC] = {};
918
919
for (int n = -1; n < 3; n++) {
920
// get Y coefficient
921
[[maybe_unused]] double k1 = _bicubic_interp_kernel(dy - (double)n);
922
923
oy2 = oy1 + n;
924
if (oy2 < 0) {
925
oy2 = 0;
926
}
927
if (oy2 > ymax) {
928
oy2 = ymax;
929
}
930
931
for (int m = -1; m < 3; m++) {
932
// get X coefficient
933
[[maybe_unused]] double k2 = k1 * _bicubic_interp_kernel((double)m - dx);
934
935
ox2 = ox1 + m;
936
if (ox2 < 0) {
937
ox2 = 0;
938
}
939
if (ox2 > xmax) {
940
ox2 = xmax;
941
}
942
943
// get pixel of original image
944
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
945
946
for (int i = 0; i < CC; i++) {
947
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
948
color[i] = Math::half_to_float(p[i]);
949
} else {
950
color[i] += p[i] * k2;
951
}
952
}
953
}
954
}
955
956
for (int i = 0; i < CC; i++) {
957
if constexpr (sizeof(T) == 1) { //byte
958
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
959
} else if constexpr (sizeof(T) == 2) {
960
if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
961
dst[i] = Math::make_half_float(color[i]); //half float
962
} else {
963
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
964
}
965
} else {
966
dst[i] = color[i];
967
}
968
}
969
}
970
}
971
}
972
973
template <int CC, typename T, ImageScaleType TYPE>
974
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
975
constexpr uint32_t FRAC_BITS = 8;
976
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
977
constexpr uint32_t FRAC_HALF = (FRAC_LEN >> 1);
978
constexpr uint32_t FRAC_MASK = FRAC_LEN - 1;
979
980
for (uint32_t i = 0; i < p_dst_height; i++) {
981
// Add 0.5 in order to interpolate based on pixel center
982
uint32_t src_yofs_up_fp = (i + 0.5) * p_src_height * FRAC_LEN / p_dst_height;
983
// Calculate nearest src pixel center above current, and truncate to get y index
984
uint32_t src_yofs_up = src_yofs_up_fp >= FRAC_HALF ? (src_yofs_up_fp - FRAC_HALF) >> FRAC_BITS : 0;
985
uint32_t src_yofs_down = (src_yofs_up_fp + FRAC_HALF) >> FRAC_BITS;
986
if (src_yofs_down >= p_src_height) {
987
src_yofs_down = p_src_height - 1;
988
}
989
// Calculate distance to pixel center of src_yofs_up
990
uint32_t src_yofs_frac = src_yofs_up_fp & FRAC_MASK;
991
src_yofs_frac = src_yofs_frac >= FRAC_HALF ? src_yofs_frac - FRAC_HALF : src_yofs_frac + FRAC_HALF;
992
993
uint32_t y_ofs_up = src_yofs_up * p_src_width * CC;
994
uint32_t y_ofs_down = src_yofs_down * p_src_width * CC;
995
996
for (uint32_t j = 0; j < p_dst_width; j++) {
997
uint32_t src_xofs_left_fp = (j + 0.5) * p_src_width * FRAC_LEN / p_dst_width;
998
uint32_t src_xofs_left = src_xofs_left_fp >= FRAC_HALF ? (src_xofs_left_fp - FRAC_HALF) >> FRAC_BITS : 0;
999
uint32_t src_xofs_right = (src_xofs_left_fp + FRAC_HALF) >> FRAC_BITS;
1000
if (src_xofs_right >= p_src_width) {
1001
src_xofs_right = p_src_width - 1;
1002
}
1003
uint32_t src_xofs_frac = src_xofs_left_fp & FRAC_MASK;
1004
src_xofs_frac = src_xofs_frac >= FRAC_HALF ? src_xofs_frac - FRAC_HALF : src_xofs_frac + FRAC_HALF;
1005
1006
src_xofs_left *= CC;
1007
src_xofs_right *= CC;
1008
1009
for (uint32_t l = 0; l < CC; l++) {
1010
if constexpr (sizeof(T) == 1) { //uint8
1011
uint32_t p00 = p_src[y_ofs_up + src_xofs_left + l] << FRAC_BITS;
1012
uint32_t p10 = p_src[y_ofs_up + src_xofs_right + l] << FRAC_BITS;
1013
uint32_t p01 = p_src[y_ofs_down + src_xofs_left + l] << FRAC_BITS;
1014
uint32_t p11 = p_src[y_ofs_down + src_xofs_right + l] << FRAC_BITS;
1015
1016
uint32_t interp_up = p00 + (((p10 - p00) * src_xofs_frac) >> FRAC_BITS);
1017
uint32_t interp_down = p01 + (((p11 - p01) * src_xofs_frac) >> FRAC_BITS);
1018
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
1019
interp >>= FRAC_BITS;
1020
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
1021
} else if constexpr (sizeof(T) == 2) {
1022
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
1023
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
1024
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
1025
const T *src = ((const T *)p_src);
1026
T *dst = ((T *)p_dst);
1027
1028
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
1029
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
1030
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
1031
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
1032
1033
float interp_up = p00 + (p10 - p00) * xofs_frac;
1034
float interp_down = p01 + (p11 - p01) * xofs_frac;
1035
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
1036
1037
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
1038
} else { //uint16
1039
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
1040
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
1041
const T *src = ((const T *)p_src);
1042
T *dst = ((T *)p_dst);
1043
1044
float p00 = src[y_ofs_up + src_xofs_left + l];
1045
float p10 = src[y_ofs_up + src_xofs_right + l];
1046
float p01 = src[y_ofs_down + src_xofs_left + l];
1047
float p11 = src[y_ofs_down + src_xofs_right + l];
1048
1049
float interp_up = p00 + (p10 - p00) * xofs_frac;
1050
float interp_down = p01 + (p11 - p01) * xofs_frac;
1051
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
1052
1053
dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
1054
}
1055
} else if constexpr (sizeof(T) == 4) { //float
1056
1057
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
1058
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
1059
const T *src = ((const T *)p_src);
1060
T *dst = ((T *)p_dst);
1061
1062
float p00 = src[y_ofs_up + src_xofs_left + l];
1063
float p10 = src[y_ofs_up + src_xofs_right + l];
1064
float p01 = src[y_ofs_down + src_xofs_left + l];
1065
float p11 = src[y_ofs_down + src_xofs_right + l];
1066
1067
float interp_up = p00 + (p10 - p00) * xofs_frac;
1068
float interp_down = p01 + (p11 - p01) * xofs_frac;
1069
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
1070
1071
dst[i * p_dst_width * CC + j * CC + l] = interp;
1072
}
1073
}
1074
}
1075
}
1076
}
1077
1078
template <int CC, typename T>
1079
static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
1080
for (uint32_t i = 0; i < p_dst_height; i++) {
1081
uint32_t src_yofs = (i + 0.5) * p_src_height / p_dst_height;
1082
uint32_t y_ofs = src_yofs * p_src_width * CC;
1083
1084
for (uint32_t j = 0; j < p_dst_width; j++) {
1085
uint32_t src_xofs = (j + 0.5) * p_src_width / p_dst_width;
1086
src_xofs *= CC;
1087
1088
for (uint32_t l = 0; l < CC; l++) {
1089
const T *src = ((const T *)p_src);
1090
T *dst = ((T *)p_dst);
1091
1092
T p = src[y_ofs + src_xofs + l];
1093
dst[i * p_dst_width * CC + j * CC + l] = p;
1094
}
1095
}
1096
}
1097
}
1098
1099
#define LANCZOS_TYPE 3
1100
1101
static float _lanczos(float p_x) {
1102
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
1103
}
1104
1105
template <int CC, typename T, ImageScaleType TYPE>
1106
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
1107
int32_t src_width = p_src_width;
1108
int32_t src_height = p_src_height;
1109
int32_t dst_height = p_dst_height;
1110
int32_t dst_width = p_dst_width;
1111
1112
uint32_t buffer_size = src_height * dst_width * CC;
1113
float *buffer = memnew_arr(float, buffer_size); // Store the first pass in a buffer
1114
1115
{ // FIRST PASS (horizontal)
1116
1117
float x_scale = float(src_width) / float(dst_width);
1118
1119
float scale_factor = MAX(x_scale, 1); // A larger kernel is required only when downscaling
1120
int32_t half_kernel = LANCZOS_TYPE * scale_factor;
1121
1122
float *kernel = memnew_arr(float, half_kernel * 2);
1123
1124
for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) {
1125
// The corresponding point on the source image
1126
float src_x = (buffer_x + 0.5f) * x_scale; // Offset by 0.5 so it uses the pixel's center
1127
int32_t start_x = MAX(0, int32_t(src_x) - half_kernel + 1);
1128
int32_t end_x = MIN(src_width - 1, int32_t(src_x) + half_kernel);
1129
1130
// Create the kernel used by all the pixels of the column
1131
for (int32_t target_x = start_x; target_x <= end_x; target_x++) {
1132
kernel[target_x - start_x] = _lanczos((target_x + 0.5f - src_x) / scale_factor);
1133
}
1134
1135
for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) {
1136
float pixel[CC] = { 0 };
1137
float weight = 0;
1138
1139
for (int32_t target_x = start_x; target_x <= end_x; target_x++) {
1140
float lanczos_val = kernel[target_x - start_x];
1141
weight += lanczos_val;
1142
1143
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
1144
1145
for (uint32_t i = 0; i < CC; i++) {
1146
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
1147
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
1148
} else {
1149
pixel[i] += src_data[i] * lanczos_val;
1150
}
1151
}
1152
}
1153
1154
float *dst_data = ((float *)buffer) + (buffer_y * dst_width + buffer_x) * CC;
1155
1156
for (uint32_t i = 0; i < CC; i++) {
1157
dst_data[i] = pixel[i] / weight; // Normalize the sum of all the samples
1158
}
1159
}
1160
}
1161
1162
memdelete_arr(kernel);
1163
} // End of first pass
1164
1165
{ // SECOND PASS (vertical + result)
1166
1167
float y_scale = float(src_height) / float(dst_height);
1168
1169
float scale_factor = MAX(y_scale, 1);
1170
int32_t half_kernel = LANCZOS_TYPE * scale_factor;
1171
1172
float *kernel = memnew_arr(float, half_kernel * 2);
1173
1174
for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) {
1175
float buffer_y = (dst_y + 0.5f) * y_scale;
1176
int32_t start_y = MAX(0, int32_t(buffer_y) - half_kernel + 1);
1177
int32_t end_y = MIN(src_height - 1, int32_t(buffer_y) + half_kernel);
1178
1179
for (int32_t target_y = start_y; target_y <= end_y; target_y++) {
1180
kernel[target_y - start_y] = _lanczos((target_y + 0.5f - buffer_y) / scale_factor);
1181
}
1182
1183
for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) {
1184
float pixel[CC] = { 0 };
1185
float weight = 0;
1186
1187
for (int32_t target_y = start_y; target_y <= end_y; target_y++) {
1188
float lanczos_val = kernel[target_y - start_y];
1189
weight += lanczos_val;
1190
1191
float *buffer_data = ((float *)buffer) + (target_y * dst_width + dst_x) * CC;
1192
1193
for (uint32_t i = 0; i < CC; i++) {
1194
pixel[i] += buffer_data[i] * lanczos_val;
1195
}
1196
}
1197
1198
T *dst_data = ((T *)p_dst) + (dst_y * dst_width + dst_x) * CC;
1199
1200
for (uint32_t i = 0; i < CC; i++) {
1201
pixel[i] /= weight;
1202
1203
if constexpr (sizeof(T) == 1) { //byte
1204
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
1205
} else if constexpr (sizeof(T) == 2) {
1206
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
1207
dst_data[i] = Math::make_half_float(pixel[i]);
1208
} else { //uint16
1209
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
1210
}
1211
1212
} else { // float
1213
dst_data[i] = pixel[i];
1214
}
1215
}
1216
}
1217
}
1218
1219
memdelete_arr(kernel);
1220
} // End of second pass
1221
1222
memdelete_arr(buffer);
1223
}
1224
1225
static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) {
1226
uint16_t alpha = MIN((uint16_t)(p_alpha * 256.0f), 256);
1227
1228
for (uint32_t i = 0; i < p_width * p_height * p_pixel_size; i++) {
1229
p_dst[i] = (p_dst[i] * (256 - alpha) + p_src[i] * alpha) >> 8;
1230
}
1231
}
1232
1233
bool Image::is_size_po2() const {
1234
return is_power_of_2(width) && is_power_of_2(height);
1235
}
1236
1237
void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
1238
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
1239
1240
int w = next_power_of_2((uint32_t)width);
1241
int h = next_power_of_2((uint32_t)height);
1242
if (p_square) {
1243
w = h = MAX(w, h);
1244
}
1245
1246
if (w == width && h == height) {
1247
if (!p_square || w == h) {
1248
return; //nothing to do
1249
}
1250
}
1251
1252
resize(w, h, p_interpolation);
1253
}
1254
1255
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
1256
ERR_FAIL_COND_MSG(data.is_empty(), "Cannot resize image before creating it, use set_data() first.");
1257
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
1258
ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
1259
ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
1260
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, vformat("Image width cannot be greater than %d pixels.", MAX_WIDTH));
1261
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, vformat("Image height cannot be greater than %d pixels.", MAX_HEIGHT));
1262
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, vformat("Too many pixels for image, maximum is %d pixels.", MAX_PIXELS));
1263
1264
if (p_width == width && p_height == height) {
1265
return;
1266
}
1267
1268
// Convert the image to 'standard' RGB(A) formats that may be resized.
1269
Format original_format = format;
1270
if (original_format == FORMAT_RGB565 || original_format == FORMAT_RGBA4444) {
1271
convert(FORMAT_RGBA8);
1272
} else if (original_format == FORMAT_RGBE9995) {
1273
convert(FORMAT_RGBH);
1274
}
1275
1276
Image dst(p_width, p_height, false, format);
1277
1278
// Setup mipmap-aware scaling
1279
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
1280
1281
Image dst2;
1282
int mip1 = 0;
1283
int mip2 = 0;
1284
float mip1_weight = 0;
1285
if (mipmap_aware) {
1286
float avg_scale = ((float)p_width / width + (float)p_height / height) * 0.5f;
1287
if (avg_scale >= 1.0f) {
1288
mipmap_aware = false;
1289
} else {
1290
float level = Math::log(1.0f / avg_scale) / Math::log(2.0f);
1291
mip1 = CLAMP((int)Math::floor(level), 0, get_mipmap_count());
1292
mip2 = CLAMP((int)Math::ceil(level), 0, get_mipmap_count());
1293
mip1_weight = 1.0f - (level - mip1);
1294
}
1295
}
1296
bool interpolate_mipmaps = mipmap_aware && mip1 != mip2;
1297
if (interpolate_mipmaps) {
1298
dst2.initialize_data(p_width, p_height, false, format);
1299
}
1300
1301
bool had_mipmaps = mipmaps;
1302
if (interpolate_mipmaps && !had_mipmaps) {
1303
generate_mipmaps();
1304
}
1305
// --
1306
1307
const uint8_t *r = data.ptr();
1308
const unsigned char *r_ptr = r;
1309
1310
uint8_t *w = dst.data.ptrw();
1311
unsigned char *w_ptr = w;
1312
1313
switch (p_interpolation) {
1314
case INTERPOLATE_NEAREST: {
1315
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
1316
switch (get_format_pixel_size(format)) {
1317
case 1:
1318
_scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1319
break;
1320
case 2:
1321
_scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1322
break;
1323
case 3:
1324
_scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1325
break;
1326
case 4:
1327
_scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1328
break;
1329
}
1330
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
1331
switch (get_format_pixel_size(format)) {
1332
case 4:
1333
_scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
1334
break;
1335
case 8:
1336
_scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
1337
break;
1338
case 12:
1339
_scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
1340
break;
1341
case 16:
1342
_scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
1343
break;
1344
}
1345
1346
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
1347
switch (get_format_pixel_size(format)) {
1348
case 2:
1349
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1350
break;
1351
case 4:
1352
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1353
break;
1354
case 6:
1355
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1356
break;
1357
case 8:
1358
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1359
break;
1360
}
1361
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
1362
switch (get_format_pixel_size(format)) {
1363
case 2:
1364
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1365
break;
1366
case 4:
1367
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1368
break;
1369
case 6:
1370
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1371
break;
1372
case 8:
1373
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
1374
break;
1375
}
1376
}
1377
1378
} break;
1379
case INTERPOLATE_BILINEAR:
1380
case INTERPOLATE_TRILINEAR: {
1381
for (int i = 0; i < 2; ++i) {
1382
int src_width;
1383
int src_height;
1384
const unsigned char *src_ptr;
1385
1386
if (!mipmap_aware) {
1387
if (i == 0) {
1388
// Standard behavior
1389
src_width = width;
1390
src_height = height;
1391
src_ptr = r_ptr;
1392
} else {
1393
// No need for a second iteration
1394
break;
1395
}
1396
} else {
1397
if (i == 0) {
1398
// Read from the first mipmap that will be interpolated
1399
// (if both levels are the same, we will not interpolate, but at least we'll sample from the right level)
1400
int64_t offs;
1401
_get_mipmap_offset_and_size(mip1, offs, src_width, src_height);
1402
src_ptr = r_ptr + offs;
1403
} else if (!interpolate_mipmaps) {
1404
// No need generate a second image
1405
break;
1406
} else {
1407
// Switch to read from the second mipmap that will be interpolated
1408
int64_t offs;
1409
_get_mipmap_offset_and_size(mip2, offs, src_width, src_height);
1410
src_ptr = r_ptr + offs;
1411
// Switch to write to the second destination image
1412
w = dst2.data.ptrw();
1413
w_ptr = w;
1414
}
1415
}
1416
1417
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
1418
switch (get_format_pixel_size(format)) {
1419
case 1:
1420
_scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1421
break;
1422
case 2:
1423
_scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1424
break;
1425
case 3:
1426
_scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1427
break;
1428
case 4:
1429
_scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1430
break;
1431
}
1432
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
1433
switch (get_format_pixel_size(format)) {
1434
case 4:
1435
_scale_bilinear<1, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1436
break;
1437
case 8:
1438
_scale_bilinear<2, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1439
break;
1440
case 12:
1441
_scale_bilinear<3, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1442
break;
1443
case 16:
1444
_scale_bilinear<4, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1445
break;
1446
}
1447
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
1448
switch (get_format_pixel_size(format)) {
1449
case 2:
1450
_scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1451
break;
1452
case 4:
1453
_scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1454
break;
1455
case 6:
1456
_scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1457
break;
1458
case 8:
1459
_scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1460
break;
1461
}
1462
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
1463
switch (get_format_pixel_size(format)) {
1464
case 2:
1465
_scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1466
break;
1467
case 4:
1468
_scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1469
break;
1470
case 6:
1471
_scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1472
break;
1473
case 8:
1474
_scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
1475
break;
1476
}
1477
}
1478
}
1479
1480
if (interpolate_mipmaps) {
1481
// Switch to read again from the first scaled mipmap to overlay it over the second
1482
r = dst.data.ptr();
1483
_overlay(r, w, mip1_weight, p_width, p_height, get_format_pixel_size(format));
1484
}
1485
1486
} break;
1487
case INTERPOLATE_CUBIC: {
1488
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
1489
switch (get_format_pixel_size(format)) {
1490
case 1:
1491
_scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1492
break;
1493
case 2:
1494
_scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1495
break;
1496
case 3:
1497
_scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1498
break;
1499
case 4:
1500
_scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1501
break;
1502
}
1503
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
1504
switch (get_format_pixel_size(format)) {
1505
case 4:
1506
_scale_cubic<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1507
break;
1508
case 8:
1509
_scale_cubic<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1510
break;
1511
case 12:
1512
_scale_cubic<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1513
break;
1514
case 16:
1515
_scale_cubic<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1516
break;
1517
}
1518
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
1519
switch (get_format_pixel_size(format)) {
1520
case 2:
1521
_scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1522
break;
1523
case 4:
1524
_scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1525
break;
1526
case 6:
1527
_scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1528
break;
1529
case 8:
1530
_scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1531
break;
1532
}
1533
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
1534
switch (get_format_pixel_size(format)) {
1535
case 2:
1536
_scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1537
break;
1538
case 4:
1539
_scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1540
break;
1541
case 6:
1542
_scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1543
break;
1544
case 8:
1545
_scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1546
break;
1547
}
1548
}
1549
} break;
1550
case INTERPOLATE_LANCZOS: {
1551
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
1552
switch (get_format_pixel_size(format)) {
1553
case 1:
1554
_scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1555
break;
1556
case 2:
1557
_scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1558
break;
1559
case 3:
1560
_scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1561
break;
1562
case 4:
1563
_scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1564
break;
1565
}
1566
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
1567
switch (get_format_pixel_size(format)) {
1568
case 4:
1569
_scale_lanczos<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1570
break;
1571
case 8:
1572
_scale_lanczos<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1573
break;
1574
case 12:
1575
_scale_lanczos<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1576
break;
1577
case 16:
1578
_scale_lanczos<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1579
break;
1580
}
1581
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
1582
switch (get_format_pixel_size(format)) {
1583
case 2:
1584
_scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1585
break;
1586
case 4:
1587
_scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1588
break;
1589
case 6:
1590
_scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1591
break;
1592
case 8:
1593
_scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
1594
break;
1595
}
1596
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
1597
switch (get_format_pixel_size(format)) {
1598
case 2:
1599
_scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1600
break;
1601
case 4:
1602
_scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1603
break;
1604
case 6:
1605
_scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1606
break;
1607
case 8:
1608
_scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
1609
break;
1610
}
1611
}
1612
} break;
1613
}
1614
1615
if (interpolate_mipmaps) {
1616
dst._copy_internals_from(dst2);
1617
}
1618
1619
if (had_mipmaps) {
1620
dst.generate_mipmaps();
1621
}
1622
1623
_copy_internals_from(dst);
1624
1625
// Reconvert the image to its original format.
1626
if (original_format != format) {
1627
convert(original_format);
1628
}
1629
}
1630
1631
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
1632
ERR_FAIL_COND_MSG(is_compressed(), "Cannot crop in compressed image formats.");
1633
ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0.");
1634
ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
1635
ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
1636
ERR_FAIL_COND_MSG(p_height <= 0, "Height of image must be greater than 0.");
1637
ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, vformat("End x position cannot be greater than %d.", MAX_WIDTH));
1638
ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, vformat("End y position cannot be greater than %d.", MAX_HEIGHT));
1639
1640
/* to save memory, cropping should be done in-place, however, since this function
1641
will most likely either not be used much, or in critical areas, for now it won't, because
1642
it's a waste of time. */
1643
1644
if (p_width == width && p_height == height && p_x == 0 && p_y == 0) {
1645
return;
1646
}
1647
1648
uint8_t pdata[16]; //largest is 16
1649
uint32_t pixel_size = get_format_pixel_size(format);
1650
1651
Image dst(p_width, p_height, false, format);
1652
1653
{
1654
const uint8_t *r = data.ptr();
1655
uint8_t *w = dst.data.ptrw();
1656
1657
int m_h = p_y + p_height;
1658
int m_w = p_x + p_width;
1659
for (int y = p_y; y < m_h; y++) {
1660
for (int x = p_x; x < m_w; x++) {
1661
if ((x >= width || y >= height)) {
1662
for (uint32_t i = 0; i < pixel_size; i++) {
1663
pdata[i] = 0;
1664
}
1665
} else {
1666
_get_pixelb(x, y, pixel_size, r, pdata);
1667
}
1668
1669
dst._put_pixelb(x - p_x, y - p_y, pixel_size, w, pdata);
1670
}
1671
}
1672
}
1673
1674
if (has_mipmaps()) {
1675
dst.generate_mipmaps();
1676
}
1677
_copy_internals_from(dst);
1678
}
1679
1680
void Image::crop(int p_width, int p_height) {
1681
crop_from_point(0, 0, p_width, p_height);
1682
}
1683
1684
void Image::rotate_90(ClockDirection p_direction) {
1685
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
1686
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
1687
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
1688
1689
bool used_mipmaps = has_mipmaps();
1690
if (used_mipmaps) {
1691
clear_mipmaps();
1692
}
1693
1694
// In-place 90 degrees rotation by following the permutation cycles.
1695
{
1696
// Explanation by example (clockwise):
1697
//
1698
// abc da
1699
// def -> eb
1700
// fc
1701
//
1702
// In memory:
1703
// 012345 012345
1704
// abcdef -> daebfc
1705
//
1706
// Permutation cycles:
1707
// (0 --a--> 1 --b--> 3 --d--> 0)
1708
// (2 --c--> 5 --f--> 4 --e--> 2)
1709
//
1710
// Applying cycles (backwards):
1711
// 0->s s=a (store)
1712
// 3->0 abcdef -> dbcdef
1713
// 1->3 dbcdef -> dbcbef
1714
// s->1 dbcbef -> dacbef
1715
//
1716
// 2->s s=c
1717
// 4->2 dacbef -> daebef
1718
// 5->4 daebef -> daebff
1719
// s->5 daebff -> daebfc
1720
1721
const int w = width;
1722
const int h = height;
1723
const int size = w * h;
1724
1725
uint8_t *data_ptr = data.ptrw();
1726
uint32_t pixel_size = get_format_pixel_size(format);
1727
1728
uint8_t single_pixel_buffer[16];
1729
1730
#define PREV_INDEX_IN_CYCLE(index) (p_direction == CLOCKWISE) ? ((h - 1 - (index % h)) * w + (index / h)) : ((index % h) * w + (w - 1 - (index / h)))
1731
1732
if (w == h) { // Square case, 4-length cycles only (plus irrelevant thus skipped 1-length cycle in the middle for odd-sized squares).
1733
for (int y = 0; y < h / 2; y++) {
1734
for (int x = 0; x < (w + 1) / 2; x++) {
1735
int current = y * w + x;
1736
memcpy(single_pixel_buffer, data_ptr + current * pixel_size, pixel_size);
1737
for (int i = 0; i < 3; i++) {
1738
int prev = PREV_INDEX_IN_CYCLE(current);
1739
memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size);
1740
current = prev;
1741
}
1742
memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size);
1743
}
1744
}
1745
} else { // Rectangular case (w != h), kinda unpredictable cycles.
1746
int permuted_pixels_count = 0;
1747
1748
for (int i = 0; i < size; i++) {
1749
int prev = PREV_INDEX_IN_CYCLE(i);
1750
if (prev == i) {
1751
// 1-length cycle, pixel remains at the same index.
1752
permuted_pixels_count++;
1753
continue;
1754
}
1755
1756
// Check whether we already processed this cycle.
1757
// We iterate over it and if we'll find an index smaller than `i` then we already
1758
// processed this cycle because we always start at the smallest index in the cycle.
1759
// TODO: Improve this naive approach, can be done better.
1760
while (prev > i) {
1761
prev = PREV_INDEX_IN_CYCLE(prev);
1762
}
1763
if (prev < i) {
1764
continue;
1765
}
1766
1767
// Save the in-cycle pixel with the smallest index (`i`).
1768
memcpy(single_pixel_buffer, data_ptr + i * pixel_size, pixel_size);
1769
1770
// Overwrite pixels one by one by the preceding pixel in the cycle.
1771
int current = i;
1772
prev = PREV_INDEX_IN_CYCLE(current);
1773
while (prev != i) {
1774
memcpy(data_ptr + current * pixel_size, data_ptr + prev * pixel_size, pixel_size);
1775
permuted_pixels_count++;
1776
1777
current = prev;
1778
prev = PREV_INDEX_IN_CYCLE(current);
1779
};
1780
1781
// Overwrite the remaining pixel in the cycle by the saved pixel with the smallest index.
1782
memcpy(data_ptr + current * pixel_size, single_pixel_buffer, pixel_size);
1783
permuted_pixels_count++;
1784
1785
if (permuted_pixels_count == size) {
1786
break;
1787
}
1788
}
1789
1790
width = h;
1791
height = w;
1792
}
1793
1794
#undef PREV_INDEX_IN_CYCLE
1795
}
1796
1797
if (used_mipmaps) {
1798
generate_mipmaps();
1799
}
1800
}
1801
1802
void Image::rotate_180() {
1803
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
1804
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
1805
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
1806
1807
bool used_mipmaps = has_mipmaps();
1808
if (used_mipmaps) {
1809
clear_mipmaps();
1810
}
1811
1812
{
1813
uint8_t *data_ptr = data.ptrw();
1814
uint32_t pixel_size = get_format_pixel_size(format);
1815
1816
uint8_t single_pixel_buffer[16];
1817
1818
uint8_t *from_begin_ptr = data_ptr;
1819
uint8_t *from_end_ptr = data_ptr + (width * height - 1) * pixel_size;
1820
1821
while (from_begin_ptr < from_end_ptr) {
1822
memcpy(single_pixel_buffer, from_begin_ptr, pixel_size);
1823
memcpy(from_begin_ptr, from_end_ptr, pixel_size);
1824
memcpy(from_end_ptr, single_pixel_buffer, pixel_size);
1825
1826
from_begin_ptr += pixel_size;
1827
from_end_ptr -= pixel_size;
1828
}
1829
}
1830
1831
if (used_mipmaps) {
1832
generate_mipmaps();
1833
}
1834
}
1835
1836
void Image::flip_y() {
1837
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_y in compressed image formats.");
1838
1839
bool used_mipmaps = has_mipmaps();
1840
if (used_mipmaps) {
1841
clear_mipmaps();
1842
}
1843
1844
{
1845
uint8_t *w = data.ptrw();
1846
uint8_t up[16];
1847
uint8_t down[16];
1848
uint32_t pixel_size = get_format_pixel_size(format);
1849
1850
for (int y = 0; y < height / 2; y++) {
1851
for (int x = 0; x < width; x++) {
1852
_get_pixelb(x, y, pixel_size, w, up);
1853
_get_pixelb(x, height - y - 1, pixel_size, w, down);
1854
1855
_put_pixelb(x, height - y - 1, pixel_size, w, up);
1856
_put_pixelb(x, y, pixel_size, w, down);
1857
}
1858
}
1859
}
1860
1861
if (used_mipmaps) {
1862
generate_mipmaps();
1863
}
1864
}
1865
1866
void Image::flip_x() {
1867
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_x in compressed image formats.");
1868
1869
bool used_mipmaps = has_mipmaps();
1870
if (used_mipmaps) {
1871
clear_mipmaps();
1872
}
1873
1874
{
1875
uint8_t *w = data.ptrw();
1876
uint8_t up[16];
1877
uint8_t down[16];
1878
uint32_t pixel_size = get_format_pixel_size(format);
1879
1880
for (int y = 0; y < height; y++) {
1881
for (int x = 0; x < width / 2; x++) {
1882
_get_pixelb(x, y, pixel_size, w, up);
1883
_get_pixelb(width - x - 1, y, pixel_size, w, down);
1884
1885
_put_pixelb(width - x - 1, y, pixel_size, w, up);
1886
_put_pixelb(x, y, pixel_size, w, down);
1887
}
1888
}
1889
}
1890
1891
if (used_mipmaps) {
1892
generate_mipmaps();
1893
}
1894
}
1895
1896
// Get mipmap size and offset.
1897
int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) {
1898
// Data offset in mipmaps (including the original texture).
1899
int64_t size = 0;
1900
1901
int w = p_width;
1902
int h = p_height;
1903
1904
// Current mipmap index in the loop below. p_mipmaps is the target mipmap index.
1905
// In this function, mipmap 0 represents the first mipmap instead of the original texture.
1906
int mm = 0;
1907
1908
int pixsize = get_format_pixel_size(p_format);
1909
int pixshift = get_format_pixel_rshift(p_format);
1910
int block = get_format_block_size(p_format);
1911
1912
// Technically, you can still compress up to 1 px no matter the format, so commenting this.
1913
//int minw, minh;
1914
//get_format_min_pixel_size(p_format, minw, minh);
1915
int minw = 1, minh = 1;
1916
1917
while (true) {
1918
int bw = w % block != 0 ? w + (block - w % block) : w;
1919
int bh = h % block != 0 ? h + (block - h % block) : h;
1920
1921
int64_t s = bw * bh;
1922
1923
s *= pixsize;
1924
s >>= pixshift;
1925
1926
size += s;
1927
1928
if (p_mipmaps >= 0) {
1929
w = MAX(minw, w >> 1);
1930
h = MAX(minh, h >> 1);
1931
} else {
1932
if (w == minw && h == minh) {
1933
break;
1934
}
1935
w = MAX(minw, w >> 1);
1936
h = MAX(minh, h >> 1);
1937
}
1938
1939
// Set mipmap size.
1940
if (r_mm_width) {
1941
*r_mm_width = w;
1942
}
1943
if (r_mm_height) {
1944
*r_mm_height = h;
1945
}
1946
1947
// Reach target mipmap.
1948
if (p_mipmaps >= 0 && mm == p_mipmaps) {
1949
break;
1950
}
1951
1952
mm++;
1953
}
1954
1955
r_mipmaps = mm;
1956
return size;
1957
}
1958
1959
template <typename Component, int CC, bool renormalize,
1960
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
1961
void (*renormalize_func)(Component *)>
1962
static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) {
1963
// Fast power of 2 mipmap generation.
1964
uint32_t dst_w = MAX(p_width >> 1, 1u);
1965
uint32_t dst_h = MAX(p_height >> 1, 1u);
1966
1967
int right_step = (p_width == 1) ? 0 : CC;
1968
int down_step = (p_height == 1) ? 0 : (p_width * CC);
1969
1970
for (uint32_t i = 0; i < dst_h; i++) {
1971
const Component *rup_ptr = &p_src[i * 2 * down_step];
1972
const Component *rdown_ptr = rup_ptr + down_step;
1973
Component *dst_ptr = &p_dst[i * dst_w * CC];
1974
uint32_t count = dst_w;
1975
1976
while (count) {
1977
count--;
1978
for (int j = 0; j < CC; j++) {
1979
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
1980
}
1981
1982
if constexpr (renormalize) {
1983
renormalize_func(dst_ptr);
1984
}
1985
1986
dst_ptr += CC;
1987
rup_ptr += right_step * 2;
1988
rdown_ptr += right_step * 2;
1989
}
1990
}
1991
}
1992
1993
void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height, bool p_renormalize) {
1994
const float *src_float = reinterpret_cast<const float *>(p_src);
1995
float *dst_float = reinterpret_cast<float *>(p_dst);
1996
1997
const uint16_t *src_u16 = reinterpret_cast<const uint16_t *>(p_src);
1998
uint16_t *dst_u16 = reinterpret_cast<uint16_t *>(p_dst);
1999
2000
const uint32_t *src_u32 = reinterpret_cast<const uint32_t *>(p_src);
2001
uint32_t *dst_u32 = reinterpret_cast<uint32_t *>(p_dst);
2002
2003
switch (p_format) {
2004
case Image::FORMAT_L8:
2005
case Image::FORMAT_R8:
2006
_generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2007
break;
2008
case Image::FORMAT_LA8:
2009
_generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2010
break;
2011
case Image::FORMAT_RG8:
2012
_generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2013
break;
2014
case Image::FORMAT_RGB8: {
2015
if (p_renormalize) {
2016
_generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2017
} else {
2018
_generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2019
}
2020
} break;
2021
case Image::FORMAT_RGBA8: {
2022
if (p_renormalize) {
2023
_generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2024
} else {
2025
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
2026
}
2027
} break;
2028
case Image::FORMAT_RGBA4444: {
2029
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgba4444, nullptr>(src_u16, dst_u16, p_width, p_height);
2030
} break;
2031
case Image::FORMAT_RGB565: {
2032
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgb565, nullptr>(src_u16, dst_u16, p_width, p_height);
2033
} break;
2034
case Image::FORMAT_RF:
2035
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2036
break;
2037
case Image::FORMAT_RGF:
2038
_generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2039
break;
2040
case Image::FORMAT_RGBF: {
2041
if (p_renormalize) {
2042
_generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2043
} else {
2044
_generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2045
}
2046
} break;
2047
case Image::FORMAT_RGBAF: {
2048
if (p_renormalize) {
2049
_generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2050
} else {
2051
_generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
2052
}
2053
} break;
2054
case Image::FORMAT_RH:
2055
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2056
break;
2057
case Image::FORMAT_RGH:
2058
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2059
break;
2060
case Image::FORMAT_RGBH: {
2061
if (p_renormalize) {
2062
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2063
} else {
2064
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2065
}
2066
} break;
2067
case Image::FORMAT_RGBAH: {
2068
if (p_renormalize) {
2069
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2070
} else {
2071
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
2072
}
2073
} break;
2074
case Image::FORMAT_RGBE9995:
2075
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, nullptr>(src_u32, dst_u32, p_width, p_height);
2076
break;
2077
case Image::FORMAT_R16:
2078
case Image::FORMAT_R16I:
2079
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2080
break;
2081
case Image::FORMAT_RG16:
2082
case Image::FORMAT_RG16I:
2083
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2084
break;
2085
case Image::FORMAT_RGB16:
2086
case Image::FORMAT_RGB16I: {
2087
if (p_renormalize) {
2088
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2089
} else {
2090
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2091
}
2092
} break;
2093
case Image::FORMAT_RGBA16:
2094
case Image::FORMAT_RGBA16I: {
2095
if (p_renormalize) {
2096
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2097
} else {
2098
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
2099
}
2100
} break;
2101
2102
default:
2103
return;
2104
}
2105
}
2106
2107
void Image::shrink_x2() {
2108
ERR_FAIL_COND(data.is_empty());
2109
Vector<uint8_t> new_data;
2110
2111
if (mipmaps) {
2112
// Just use the lower mipmap as base and copy all.
2113
int64_t ofs = get_mipmap_offset(1);
2114
int64_t new_size = data.size() - ofs;
2115
2116
new_data.resize(new_size);
2117
ERR_FAIL_COND(new_data.is_empty());
2118
2119
memcpy(new_data.ptrw(), data.ptr() + ofs, new_size);
2120
} else {
2121
// Generate a mipmap and replace the original.
2122
ERR_FAIL_COND(is_compressed());
2123
2124
new_data.resize((width / 2) * (height / 2) * get_format_pixel_size(format));
2125
ERR_FAIL_COND(data.is_empty() || new_data.is_empty());
2126
2127
_generate_mipmap_from_format(format, data.ptr(), new_data.ptrw(), width, height, false);
2128
}
2129
2130
width = MAX(width / 2, 1);
2131
height = MAX(height / 2, 1);
2132
data = new_data;
2133
}
2134
2135
void Image::normalize() {
2136
bool used_mipmaps = has_mipmaps();
2137
if (used_mipmaps) {
2138
clear_mipmaps();
2139
}
2140
2141
for (int y = 0; y < height; y++) {
2142
for (int x = 0; x < width; x++) {
2143
Color c = get_pixel(x, y);
2144
Vector3 v(c.r * 2.0 - 1.0, c.g * 2.0 - 1.0, c.b * 2.0 - 1.0);
2145
v.normalize();
2146
c.r = v.x * 0.5 + 0.5;
2147
c.g = v.y * 0.5 + 0.5;
2148
c.b = v.z * 0.5 + 0.5;
2149
set_pixel(x, y, c);
2150
}
2151
}
2152
2153
if (used_mipmaps) {
2154
generate_mipmaps(true);
2155
}
2156
}
2157
2158
Error Image::generate_mipmaps(bool p_renormalize) {
2159
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
2160
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
2161
2162
int gen_mipmap_count;
2163
2164
int64_t size = _get_dst_image_size(width, height, format, gen_mipmap_count);
2165
data.resize(size);
2166
uint8_t *wp = data.ptrw();
2167
2168
int prev_ofs = 0;
2169
int prev_h = height;
2170
int prev_w = width;
2171
2172
for (int i = 1; i <= gen_mipmap_count; i++) {
2173
int64_t ofs;
2174
int w, h;
2175
_get_mipmap_offset_and_size(i, ofs, w, h);
2176
2177
_generate_mipmap_from_format(format, wp + prev_ofs, wp + ofs, prev_w, prev_h, p_renormalize);
2178
2179
prev_ofs = ofs;
2180
prev_w = w;
2181
prev_h = h;
2182
}
2183
2184
mipmaps = true;
2185
2186
return OK;
2187
}
2188
2189
Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) {
2190
LocalVector<double> normal_sat_vec; //summed area table
2191
int normal_w = 0, normal_h = 0;
2192
2193
ERR_FAIL_COND_V_MSG(p_normal_map.is_null() || p_normal_map->is_empty(), ERR_INVALID_PARAMETER, "Must provide a valid normal map for roughness mipmaps");
2194
2195
Ref<Image> nm = p_normal_map->duplicate();
2196
if (nm->is_compressed()) {
2197
nm->decompress();
2198
}
2199
2200
normal_w = nm->get_width();
2201
normal_h = nm->get_height();
2202
2203
normal_sat_vec.resize(normal_w * normal_h * 3);
2204
double *normal_sat = normal_sat_vec.ptr();
2205
2206
// Create summed area table.
2207
for (int y = 0; y < normal_h; y++) {
2208
double line_sum[3] = { 0, 0, 0 };
2209
for (int x = 0; x < normal_w; x++) {
2210
double normal[3];
2211
Color color = nm->get_pixel(x, y);
2212
normal[0] = color.r * 2.0 - 1.0;
2213
normal[1] = color.g * 2.0 - 1.0;
2214
normal[2] = Math::sqrt(MAX(0.0, 1.0 - (normal[0] * normal[0] + normal[1] * normal[1]))); //reconstruct if missing
2215
2216
line_sum[0] += normal[0];
2217
line_sum[1] += normal[1];
2218
line_sum[2] += normal[2];
2219
2220
uint32_t ofs = (y * normal_w + x) * 3;
2221
2222
normal_sat[ofs + 0] = line_sum[0];
2223
normal_sat[ofs + 1] = line_sum[1];
2224
normal_sat[ofs + 2] = line_sum[2];
2225
2226
if (y > 0) {
2227
uint32_t prev_ofs = ((y - 1) * normal_w + x) * 3;
2228
normal_sat[ofs + 0] += normal_sat[prev_ofs + 0];
2229
normal_sat[ofs + 1] += normal_sat[prev_ofs + 1];
2230
normal_sat[ofs + 2] += normal_sat[prev_ofs + 2];
2231
}
2232
}
2233
}
2234
2235
int mmcount;
2236
2237
_get_dst_image_size(width, height, format, mmcount);
2238
2239
uint8_t *base_ptr = data.ptrw();
2240
2241
for (int i = 1; i <= mmcount; i++) {
2242
int64_t ofs;
2243
int w, h;
2244
_get_mipmap_offset_and_size(i, ofs, w, h);
2245
uint8_t *ptr = &base_ptr[ofs];
2246
2247
for (int x = 0; x < w; x++) {
2248
for (int y = 0; y < h; y++) {
2249
int from_x = x * normal_w / w;
2250
int from_y = y * normal_h / h;
2251
int to_x = (x + 1) * normal_w / w;
2252
int to_y = (y + 1) * normal_h / h;
2253
to_x = MIN(to_x - 1, normal_w);
2254
to_y = MIN(to_y - 1, normal_h);
2255
2256
int size_x = (to_x - from_x) + 1;
2257
int size_y = (to_y - from_y) + 1;
2258
2259
//summed area table version (much faster)
2260
2261
double avg[3] = { 0, 0, 0 };
2262
2263
if (from_x > 0 && from_y > 0) {
2264
uint32_t tofs = ((from_y - 1) * normal_w + (from_x - 1)) * 3;
2265
avg[0] += normal_sat[tofs + 0];
2266
avg[1] += normal_sat[tofs + 1];
2267
avg[2] += normal_sat[tofs + 2];
2268
}
2269
2270
if (from_y > 0 && to_x > 0) {
2271
uint32_t tofs = ((from_y - 1) * normal_w + to_x) * 3;
2272
avg[0] -= normal_sat[tofs + 0];
2273
avg[1] -= normal_sat[tofs + 1];
2274
avg[2] -= normal_sat[tofs + 2];
2275
}
2276
2277
if (from_x > 0 && to_y > 0) {
2278
uint32_t tofs = (to_y * normal_w + (from_x - 1)) * 3;
2279
avg[0] -= normal_sat[tofs + 0];
2280
avg[1] -= normal_sat[tofs + 1];
2281
avg[2] -= normal_sat[tofs + 2];
2282
}
2283
2284
if (to_y > 0 && to_x > 0) {
2285
uint32_t tofs = (to_y * normal_w + to_x) * 3;
2286
avg[0] += normal_sat[tofs + 0];
2287
avg[1] += normal_sat[tofs + 1];
2288
avg[2] += normal_sat[tofs + 2];
2289
}
2290
2291
double div = double(size_x * size_y);
2292
Vector3 vec(avg[0] / div, avg[1] / div, avg[2] / div);
2293
2294
float r = vec.length();
2295
2296
int pixel_ofs = y * w + x;
2297
Color c = _get_color_at_ofs(ptr, pixel_ofs);
2298
2299
float roughness = 0;
2300
2301
switch (p_roughness_channel) {
2302
case ROUGHNESS_CHANNEL_R: {
2303
roughness = c.r;
2304
} break;
2305
case ROUGHNESS_CHANNEL_G: {
2306
roughness = c.g;
2307
} break;
2308
case ROUGHNESS_CHANNEL_B: {
2309
roughness = c.b;
2310
} break;
2311
case ROUGHNESS_CHANNEL_L: {
2312
roughness = c.get_v();
2313
} break;
2314
case ROUGHNESS_CHANNEL_A: {
2315
roughness = c.a;
2316
} break;
2317
}
2318
2319
float variance = 0;
2320
if (r < 1.0f) {
2321
float r2 = r * r;
2322
float kappa = (3.0f * r - r * r2) / (1.0f - r2);
2323
variance = 0.25f / kappa;
2324
}
2325
2326
float threshold = 0.4;
2327
roughness = Math::sqrt(roughness * roughness + MIN(3.0f * variance, threshold * threshold));
2328
2329
switch (p_roughness_channel) {
2330
case ROUGHNESS_CHANNEL_R: {
2331
c.r = roughness;
2332
} break;
2333
case ROUGHNESS_CHANNEL_G: {
2334
c.g = roughness;
2335
} break;
2336
case ROUGHNESS_CHANNEL_B: {
2337
c.b = roughness;
2338
} break;
2339
case ROUGHNESS_CHANNEL_L: {
2340
c.r = roughness;
2341
c.g = roughness;
2342
c.b = roughness;
2343
} break;
2344
case ROUGHNESS_CHANNEL_A: {
2345
c.a = roughness;
2346
} break;
2347
}
2348
2349
_set_color_at_ofs(ptr, pixel_ofs, c);
2350
}
2351
}
2352
}
2353
2354
return OK;
2355
}
2356
2357
void Image::clear_mipmaps() {
2358
if (!mipmaps) {
2359
return;
2360
}
2361
2362
if (is_empty()) {
2363
return;
2364
}
2365
2366
int64_t ofs;
2367
int w, h;
2368
_get_mipmap_offset_and_size(1, ofs, w, h);
2369
data.resize(ofs);
2370
2371
mipmaps = false;
2372
}
2373
2374
bool Image::is_empty() const {
2375
return (data.is_empty());
2376
}
2377
2378
Vector<uint8_t> Image::get_data() const {
2379
return data;
2380
}
2381
2382
Ref<Image> Image::create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
2383
Ref<Image> image;
2384
image.instantiate();
2385
image->initialize_data(p_width, p_height, p_use_mipmaps, p_format);
2386
return image;
2387
}
2388
2389
Ref<Image> Image::create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
2390
Ref<Image> image;
2391
image.instantiate();
2392
image->initialize_data(p_width, p_height, p_use_mipmaps, p_format, p_data);
2393
return image;
2394
}
2395
2396
void Image::set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
2397
initialize_data(p_width, p_height, p_use_mipmaps, p_format, p_data);
2398
}
2399
2400
void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
2401
ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width));
2402
ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height));
2403
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
2404
vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH));
2405
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
2406
vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT));
2407
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
2408
vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS));
2409
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format));
2410
2411
int mm = 0;
2412
int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
2413
data.resize(size);
2414
2415
{
2416
uint8_t *w = data.ptrw();
2417
memset(w, 0, size);
2418
}
2419
2420
width = p_width;
2421
height = p_height;
2422
mipmaps = p_use_mipmaps;
2423
format = p_format;
2424
}
2425
2426
void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
2427
ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width));
2428
ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height));
2429
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
2430
vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH));
2431
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
2432
vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT));
2433
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
2434
vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS));
2435
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format));
2436
2437
int mm;
2438
int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
2439
2440
if (unlikely(p_data.size() != size)) {
2441
String description_mipmaps = get_format_name(p_format) + " ";
2442
if (p_use_mipmaps) {
2443
const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format);
2444
if (num_mipmaps != 1) {
2445
description_mipmaps += vformat("with %d mipmaps", num_mipmaps);
2446
} else {
2447
description_mipmaps += "with 1 mipmap";
2448
}
2449
} else {
2450
description_mipmaps += "without mipmaps";
2451
}
2452
const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps);
2453
ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size()));
2454
}
2455
2456
height = p_height;
2457
width = p_width;
2458
format = p_format;
2459
data = p_data;
2460
2461
mipmaps = p_use_mipmaps;
2462
}
2463
2464
void Image::initialize_data(const char **p_xpm) {
2465
int size_width = 0;
2466
int size_height = 0;
2467
int pixelchars = 0;
2468
mipmaps = false;
2469
bool has_alpha = false;
2470
2471
enum Status {
2472
READING_HEADER,
2473
READING_COLORS,
2474
READING_PIXELS,
2475
DONE
2476
};
2477
2478
Status status = READING_HEADER;
2479
int line = 0;
2480
2481
HashMap<String, Color> colormap;
2482
int colormap_size = 0;
2483
uint32_t pixel_size = 0;
2484
uint8_t *data_write = nullptr;
2485
2486
while (status != DONE) {
2487
const char *line_ptr = p_xpm[line];
2488
2489
switch (status) {
2490
case READING_HEADER: {
2491
String line_str = line_ptr;
2492
line_str = line_str.replace_char('\t', ' ');
2493
2494
size_width = line_str.get_slicec(' ', 0).to_int();
2495
size_height = line_str.get_slicec(' ', 1).to_int();
2496
colormap_size = line_str.get_slicec(' ', 2).to_int();
2497
pixelchars = line_str.get_slicec(' ', 3).to_int();
2498
ERR_FAIL_COND(colormap_size > 32766);
2499
ERR_FAIL_COND(pixelchars > 5);
2500
ERR_FAIL_COND(size_width > 32767);
2501
ERR_FAIL_COND(size_height > 32767);
2502
status = READING_COLORS;
2503
} break;
2504
case READING_COLORS: {
2505
String colorstring;
2506
for (int i = 0; i < pixelchars; i++) {
2507
colorstring += *line_ptr;
2508
line_ptr++;
2509
}
2510
//skip spaces
2511
while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) {
2512
if (*line_ptr == 0) {
2513
break;
2514
}
2515
line_ptr++;
2516
}
2517
if (*line_ptr == 'c') {
2518
line_ptr++;
2519
while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) {
2520
if (*line_ptr == 0) {
2521
break;
2522
}
2523
line_ptr++;
2524
}
2525
2526
if (*line_ptr == '#') {
2527
line_ptr++;
2528
uint8_t col_r = 0;
2529
uint8_t col_g = 0;
2530
uint8_t col_b = 0;
2531
//uint8_t col_a=255;
2532
2533
for (int i = 0; i < 6; i++) {
2534
char v = line_ptr[i];
2535
2536
if (is_digit(v)) {
2537
v -= '0';
2538
} else if (v >= 'A' && v <= 'F') {
2539
v = (v - 'A') + 10;
2540
} else if (v >= 'a' && v <= 'f') {
2541
v = (v - 'a') + 10;
2542
} else {
2543
break;
2544
}
2545
2546
switch (i) {
2547
case 0:
2548
col_r = v << 4;
2549
break;
2550
case 1:
2551
col_r |= v;
2552
break;
2553
case 2:
2554
col_g = v << 4;
2555
break;
2556
case 3:
2557
col_g |= v;
2558
break;
2559
case 4:
2560
col_b = v << 4;
2561
break;
2562
case 5:
2563
col_b |= v;
2564
break;
2565
}
2566
}
2567
2568
// magenta mask
2569
if (col_r == 255 && col_g == 0 && col_b == 255) {
2570
colormap[colorstring] = Color(0, 0, 0, 0);
2571
has_alpha = true;
2572
} else {
2573
colormap[colorstring] = Color(col_r / 255.0, col_g / 255.0, col_b / 255.0, 1.0);
2574
}
2575
}
2576
}
2577
if (line == colormap_size) {
2578
status = READING_PIXELS;
2579
initialize_data(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8);
2580
data_write = data.ptrw();
2581
pixel_size = has_alpha ? 4 : 3;
2582
}
2583
} break;
2584
case READING_PIXELS: {
2585
int y = line - colormap_size - 1;
2586
for (int x = 0; x < size_width; x++) {
2587
char pixelstr[6] = { 0, 0, 0, 0, 0, 0 };
2588
for (int i = 0; i < pixelchars; i++) {
2589
pixelstr[i] = line_ptr[x * pixelchars + i];
2590
}
2591
2592
Color *colorptr = colormap.getptr(pixelstr);
2593
ERR_FAIL_NULL(colorptr);
2594
uint8_t pixel[4];
2595
for (uint32_t i = 0; i < pixel_size; i++) {
2596
pixel[i] = CLAMP((*colorptr)[i] * 255, 0, 255);
2597
}
2598
_put_pixelb(x, y, pixel_size, data_write, pixel);
2599
}
2600
2601
if (y == (size_height - 1)) {
2602
status = DONE;
2603
}
2604
} break;
2605
default: {
2606
}
2607
}
2608
2609
line++;
2610
}
2611
}
2612
#define DETECT_ALPHA_MAX_THRESHOLD 254
2613
#define DETECT_ALPHA_MIN_THRESHOLD 2
2614
2615
#define DETECT_ALPHA(m_value) \
2616
{ \
2617
uint8_t value = m_value; \
2618
if (value < DETECT_ALPHA_MIN_THRESHOLD) \
2619
bit = true; \
2620
else if (value < DETECT_ALPHA_MAX_THRESHOLD) { \
2621
detected = true; \
2622
break; \
2623
} \
2624
}
2625
2626
#define DETECT_NON_ALPHA(m_value) \
2627
{ \
2628
uint8_t value = m_value; \
2629
if (value > 0) { \
2630
detected = true; \
2631
break; \
2632
} \
2633
}
2634
2635
bool Image::is_invisible() const {
2636
int w, h;
2637
int64_t len;
2638
_get_mipmap_offset_and_size(1, len, w, h);
2639
2640
if (len == 0) {
2641
return true;
2642
}
2643
2644
switch (format) {
2645
case FORMAT_LA8: {
2646
const int pixel_count = len / 2;
2647
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
2648
2649
for (int i = 0; i < pixel_count; i++) {
2650
if ((pixeldata[i] & 0xFF00) != 0) {
2651
return false;
2652
}
2653
}
2654
} break;
2655
case FORMAT_RGBA8: {
2656
const int pixel_count = len / 4;
2657
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
2658
2659
for (int i = 0; i < pixel_count; i++) {
2660
if ((pixeldata[i] & 0xFF000000) != 0) {
2661
return false;
2662
}
2663
}
2664
} break;
2665
case FORMAT_RGBA4444: {
2666
const int pixel_count = len / 2;
2667
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
2668
2669
for (int i = 0; i < pixel_count; i++) {
2670
if ((pixeldata[i] & 0x000F) != 0) {
2671
return false;
2672
}
2673
}
2674
} break;
2675
case FORMAT_RGBAH: {
2676
// The alpha mask accounts for the sign bit.
2677
const int pixel_count = len / 8;
2678
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
2679
2680
for (int i = 0; i < pixel_count; i++) {
2681
if ((pixeldata[i * 4 + 3] & 0x7FFF) != 0) {
2682
return false;
2683
}
2684
}
2685
} break;
2686
case FORMAT_RGBAF: {
2687
// The alpha mask accounts for the sign bit.
2688
const int pixel_count = len / 16;
2689
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
2690
2691
for (int i = 0; i < pixel_count; i++) {
2692
if ((pixeldata[i * 4 + 3] & 0x7FFFFFFF) != 0) {
2693
return false;
2694
}
2695
}
2696
} break;
2697
case FORMAT_RGBA16:
2698
case FORMAT_RGBA16I: {
2699
const int pixel_count = len / 8;
2700
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
2701
2702
for (int i = 0; i < pixel_count; i++) {
2703
if (pixeldata[i * 4 + 3] != 0) {
2704
return false;
2705
}
2706
}
2707
} break;
2708
default: {
2709
// Formats that are compressed or don't support alpha channels are presumed to be visible.
2710
return false;
2711
}
2712
}
2713
2714
// Every pixel has been checked, the image is invisible.
2715
return true;
2716
}
2717
2718
Image::AlphaMode Image::detect_alpha() const {
2719
int64_t len = data.size();
2720
2721
if (len == 0) {
2722
return ALPHA_NONE;
2723
}
2724
2725
int w, h;
2726
_get_mipmap_offset_and_size(1, len, w, h);
2727
2728
const uint8_t *r = data.ptr();
2729
const unsigned char *data_ptr = r;
2730
2731
bool bit = false;
2732
bool detected = false;
2733
2734
switch (format) {
2735
case FORMAT_LA8: {
2736
for (int i = 0; i < (len >> 1); i++) {
2737
DETECT_ALPHA(data_ptr[(i << 1) + 1]);
2738
}
2739
2740
} break;
2741
case FORMAT_RGBA8: {
2742
for (int i = 0; i < (len >> 2); i++) {
2743
DETECT_ALPHA(data_ptr[(i << 2) + 3])
2744
}
2745
2746
} break;
2747
case FORMAT_DXT3:
2748
case FORMAT_DXT5: {
2749
detected = true;
2750
} break;
2751
default: {
2752
}
2753
}
2754
2755
if (detected) {
2756
return ALPHA_BLEND;
2757
} else if (bit) {
2758
return ALPHA_BIT;
2759
} else {
2760
return ALPHA_NONE;
2761
}
2762
}
2763
2764
Error Image::load(const String &p_path) {
2765
String path = ResourceUID::ensure_path(p_path);
2766
#ifdef DEBUG_ENABLED
2767
if (path.begins_with("res://") && ResourceLoader::exists(path)) {
2768
WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path));
2769
}
2770
#endif
2771
return ImageLoader::load_image(path, this);
2772
}
2773
2774
Ref<Image> Image::load_from_file(const String &p_path) {
2775
String path = ResourceUID::ensure_path(p_path);
2776
#ifdef DEBUG_ENABLED
2777
if (path.begins_with("res://") && ResourceLoader::exists(path)) {
2778
WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path));
2779
}
2780
#endif
2781
Ref<Image> image;
2782
image.instantiate();
2783
Error err = ImageLoader::load_image(path, image);
2784
if (err != OK) {
2785
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Failed to load image. Error %d", err));
2786
}
2787
return image;
2788
}
2789
2790
Error Image::save_png(const String &p_path) const {
2791
if (save_png_func == nullptr) {
2792
return ERR_UNAVAILABLE;
2793
}
2794
2795
return save_png_func(p_path, Ref<Image>((Image *)this));
2796
}
2797
2798
Error Image::save_jpg(const String &p_path, float p_quality) const {
2799
if (save_jpg_func == nullptr) {
2800
return ERR_UNAVAILABLE;
2801
}
2802
2803
return save_jpg_func(p_path, Ref<Image>((Image *)this), p_quality);
2804
}
2805
2806
Vector<uint8_t> Image::save_png_to_buffer() const {
2807
if (save_png_buffer_func == nullptr) {
2808
return Vector<uint8_t>();
2809
}
2810
2811
return save_png_buffer_func(Ref<Image>((Image *)this));
2812
}
2813
2814
Vector<uint8_t> Image::save_jpg_to_buffer(float p_quality) const {
2815
if (save_jpg_buffer_func == nullptr) {
2816
return Vector<uint8_t>();
2817
}
2818
2819
return save_jpg_buffer_func(Ref<Image>((Image *)this), p_quality);
2820
}
2821
2822
Error Image::save_exr(const String &p_path, bool p_grayscale) const {
2823
if (save_exr_func == nullptr) {
2824
return ERR_UNAVAILABLE;
2825
}
2826
2827
return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale);
2828
}
2829
2830
Vector<uint8_t> Image::save_exr_to_buffer(bool p_grayscale) const {
2831
if (save_exr_buffer_func == nullptr) {
2832
return Vector<uint8_t>();
2833
}
2834
return save_exr_buffer_func(Ref<Image>((Image *)this), p_grayscale);
2835
}
2836
2837
Error Image::save_dds(const String &p_path) const {
2838
if (save_dds_func == nullptr) {
2839
return ERR_UNAVAILABLE;
2840
}
2841
2842
return save_dds_func(p_path, Ref<Image>((Image *)this));
2843
}
2844
2845
Vector<uint8_t> Image::save_dds_to_buffer() const {
2846
if (save_dds_buffer_func == nullptr) {
2847
return Vector<uint8_t>();
2848
}
2849
return save_dds_buffer_func(Ref<Image>((Image *)this));
2850
}
2851
2852
Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const {
2853
if (save_webp_func == nullptr) {
2854
return ERR_UNAVAILABLE;
2855
}
2856
ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), ERR_INVALID_PARAMETER, vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality));
2857
2858
return save_webp_func(p_path, Ref<Image>((Image *)this), p_lossy, p_quality);
2859
}
2860
2861
Vector<uint8_t> Image::save_webp_to_buffer(const bool p_lossy, const float p_quality) const {
2862
if (save_webp_buffer_func == nullptr) {
2863
return Vector<uint8_t>();
2864
}
2865
ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), Vector<uint8_t>(), vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality));
2866
2867
return save_webp_buffer_func(Ref<Image>((Image *)this), p_lossy, p_quality);
2868
}
2869
2870
int64_t Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) {
2871
int mm;
2872
return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmaps ? -1 : 0);
2873
}
2874
2875
int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format) {
2876
int mm;
2877
_get_dst_image_size(p_width, p_height, p_format, mm, -1);
2878
return mm;
2879
}
2880
2881
Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap) {
2882
int mm;
2883
Size2i ret;
2884
_get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap, &ret.x, &ret.y);
2885
return ret;
2886
}
2887
2888
int64_t Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) {
2889
if (p_mipmap <= 0) {
2890
return 0;
2891
}
2892
int mm;
2893
return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1);
2894
}
2895
2896
int64_t Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) {
2897
if (p_mipmap <= 0) {
2898
r_w = p_width;
2899
r_h = p_height;
2900
return 0;
2901
}
2902
int mm;
2903
return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1, &r_w, &r_h);
2904
}
2905
2906
bool Image::is_compressed() const {
2907
return is_format_compressed(format);
2908
}
2909
2910
bool Image::is_format_compressed(Format p_format) {
2911
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
2912
}
2913
2914
Error Image::decompress() {
2915
if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc) {
2916
_image_decompress_bc(this);
2917
} else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) {
2918
_image_decompress_bptc(this);
2919
} else if (format == FORMAT_ETC && _image_decompress_etc1) {
2920
_image_decompress_etc1(this);
2921
} else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) {
2922
_image_decompress_etc2(this);
2923
} else if (format >= FORMAT_ASTC_4x4 && format <= FORMAT_ASTC_8x8_HDR && _image_decompress_astc) {
2924
_image_decompress_astc(this);
2925
} else {
2926
return ERR_UNAVAILABLE;
2927
}
2928
return OK;
2929
}
2930
2931
bool Image::can_decompress(const String &p_format_tag) {
2932
if (p_format_tag == "astc") {
2933
return _image_decompress_astc != nullptr;
2934
} else if (p_format_tag == "bptc") {
2935
return _image_decompress_bptc != nullptr;
2936
} else if (p_format_tag == "etc2") {
2937
return _image_decompress_etc2 != nullptr;
2938
} else if (p_format_tag == "s3tc") {
2939
return _image_decompress_bc != nullptr;
2940
}
2941
return false;
2942
}
2943
2944
Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
2945
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
2946
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
2947
return compress_from_channels(p_mode, detect_used_channels(p_source), p_astc_format);
2948
}
2949
2950
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
2951
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
2952
2953
// RenderingDevice only.
2954
if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) {
2955
switch (p_mode) {
2956
case COMPRESS_BPTC: {
2957
// BC7 is unsupported currently.
2958
if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) {
2959
Error result = _image_compress_bptc_rd_func(this, p_channels);
2960
2961
// If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
2962
if (result == OK) {
2963
return OK;
2964
}
2965
}
2966
} break;
2967
case COMPRESS_S3TC: {
2968
if (_image_compress_bc_rd_func) {
2969
Error result = _image_compress_bc_rd_func(this, p_channels);
2970
2971
// If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
2972
if (result == OK) {
2973
return OK;
2974
}
2975
}
2976
} break;
2977
2978
default: {
2979
}
2980
}
2981
}
2982
2983
switch (p_mode) {
2984
case COMPRESS_S3TC: {
2985
ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE);
2986
_image_compress_bc_func(this, p_channels);
2987
} break;
2988
case COMPRESS_ETC: {
2989
ERR_FAIL_NULL_V(_image_compress_etc1_func, ERR_UNAVAILABLE);
2990
_image_compress_etc1_func(this);
2991
} break;
2992
case COMPRESS_ETC2: {
2993
ERR_FAIL_NULL_V(_image_compress_etc2_func, ERR_UNAVAILABLE);
2994
_image_compress_etc2_func(this, p_channels);
2995
} break;
2996
case COMPRESS_BPTC: {
2997
ERR_FAIL_NULL_V(_image_compress_bptc_func, ERR_UNAVAILABLE);
2998
_image_compress_bptc_func(this, p_channels);
2999
} break;
3000
case COMPRESS_ASTC: {
3001
ERR_FAIL_NULL_V(_image_compress_astc_func, ERR_UNAVAILABLE);
3002
_image_compress_astc_func(this, p_astc_format);
3003
} break;
3004
case COMPRESS_MAX: {
3005
ERR_FAIL_V(ERR_INVALID_PARAMETER);
3006
} break;
3007
}
3008
3009
return OK;
3010
}
3011
3012
Image::Image(const char **p_xpm) {
3013
width = 0;
3014
height = 0;
3015
mipmaps = false;
3016
format = FORMAT_L8;
3017
3018
initialize_data(p_xpm);
3019
}
3020
3021
Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
3022
width = 0;
3023
height = 0;
3024
mipmaps = p_use_mipmaps;
3025
format = FORMAT_L8;
3026
3027
initialize_data(p_width, p_height, p_use_mipmaps, p_format);
3028
}
3029
3030
Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
3031
width = 0;
3032
height = 0;
3033
mipmaps = p_mipmaps;
3034
format = FORMAT_L8;
3035
3036
initialize_data(p_width, p_height, p_mipmaps, p_format, p_data);
3037
}
3038
3039
Rect2i Image::get_used_rect() const {
3040
if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) {
3041
return Rect2i(0, 0, width, height);
3042
}
3043
3044
int len = data.size();
3045
3046
if (len == 0) {
3047
return Rect2i();
3048
}
3049
3050
int minx = 0xFFFFFF, miny = 0xFFFFFFF;
3051
int maxx = -1, maxy = -1;
3052
for (int j = 0; j < height; j++) {
3053
for (int i = 0; i < width; i++) {
3054
if (!(get_pixel(i, j).a > 0)) {
3055
continue;
3056
}
3057
if (i > maxx) {
3058
maxx = i;
3059
}
3060
if (j > maxy) {
3061
maxy = j;
3062
}
3063
if (i < minx) {
3064
minx = i;
3065
}
3066
if (j < miny) {
3067
miny = j;
3068
}
3069
}
3070
}
3071
3072
if (maxx == -1) {
3073
return Rect2i();
3074
} else {
3075
return Rect2i(minx, miny, maxx - minx + 1, maxy - miny + 1);
3076
}
3077
}
3078
3079
Ref<Image> Image::get_region(const Rect2i &p_region) const {
3080
Ref<Image> img = memnew(Image(p_region.size.x, p_region.size.y, mipmaps, format));
3081
img->blit_rect(Ref<Image>((Image *)this), p_region, Point2i(0, 0));
3082
return img;
3083
}
3084
3085
void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const {
3086
r_clipped_dest_rect.position = p_dest;
3087
r_clipped_src_rect = p_src_rect;
3088
3089
if (r_clipped_src_rect.position.x < 0) {
3090
r_clipped_dest_rect.position.x -= r_clipped_src_rect.position.x;
3091
r_clipped_src_rect.size.x += r_clipped_src_rect.position.x;
3092
r_clipped_src_rect.position.x = 0;
3093
}
3094
if (r_clipped_src_rect.position.y < 0) {
3095
r_clipped_dest_rect.position.y -= r_clipped_src_rect.position.y;
3096
r_clipped_src_rect.size.y += r_clipped_src_rect.position.y;
3097
r_clipped_src_rect.position.y = 0;
3098
}
3099
3100
if (r_clipped_dest_rect.position.x < 0) {
3101
r_clipped_src_rect.position.x -= r_clipped_dest_rect.position.x;
3102
r_clipped_src_rect.size.x += r_clipped_dest_rect.position.x;
3103
r_clipped_dest_rect.position.x = 0;
3104
}
3105
if (r_clipped_dest_rect.position.y < 0) {
3106
r_clipped_src_rect.position.y -= r_clipped_dest_rect.position.y;
3107
r_clipped_src_rect.size.y += r_clipped_dest_rect.position.y;
3108
r_clipped_dest_rect.position.y = 0;
3109
}
3110
3111
r_clipped_src_rect.size.x = MAX(0, MIN(r_clipped_src_rect.size.x, MIN(p_src->width - r_clipped_src_rect.position.x, width - r_clipped_dest_rect.position.x)));
3112
r_clipped_src_rect.size.y = MAX(0, MIN(r_clipped_src_rect.size.y, MIN(p_src->height - r_clipped_src_rect.position.y, height - r_clipped_dest_rect.position.y)));
3113
3114
r_clipped_dest_rect.size.x = r_clipped_src_rect.size.x;
3115
r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y;
3116
}
3117
3118
void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
3119
ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blit_rect an image: invalid source Image object.");
3120
int dsize = data.size();
3121
int srcdsize = p_src->data.size();
3122
ERR_FAIL_COND(dsize == 0);
3123
ERR_FAIL_COND(srcdsize == 0);
3124
ERR_FAIL_COND(format != p_src->format);
3125
ERR_FAIL_COND_MSG(is_compressed(), "Cannot blit_rect in compressed image formats.");
3126
3127
Rect2i src_rect;
3128
Rect2i dest_rect;
3129
_get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
3130
if (!src_rect.has_area() || !dest_rect.has_area()) {
3131
return;
3132
}
3133
3134
uint8_t *wp = data.ptrw();
3135
uint8_t *dst_data_ptr = wp;
3136
3137
const uint8_t *rp = p_src->data.ptr();
3138
const uint8_t *src_data_ptr = rp;
3139
3140
int pixel_size = get_format_pixel_size(format);
3141
3142
// If the rect width is equivalent for both src and dst and the x offset is 0, we can blit in a single memcpy.
3143
// Else, we do a per-line copy.
3144
if ((dest_rect.size.x == p_src->width) && (p_src->width == width) && (dest_rect.position.x == 0) && (src_rect.position.x == 0)) {
3145
const uint8_t *src = &src_data_ptr[(src_rect.position.y * p_src->width) * pixel_size];
3146
uint8_t *dst = &dst_data_ptr[(dest_rect.position.y * width) * pixel_size];
3147
memcpy(dst, src, width * dest_rect.size.y * pixel_size);
3148
} else {
3149
for (int i = 0; i < dest_rect.size.y; i++) {
3150
const uint8_t *src = &src_data_ptr[((src_rect.position.y + i) * p_src->width + src_rect.position.x) * pixel_size];
3151
uint8_t *dst = &dst_data_ptr[((dest_rect.position.y + i) * width + dest_rect.position.x) * pixel_size];
3152
memcpy(dst, src, pixel_size * dest_rect.size.x);
3153
}
3154
}
3155
}
3156
3157
void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
3158
ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blit_rect_mask an image: invalid source Image object.");
3159
ERR_FAIL_COND_MSG(p_mask.is_null(), "Cannot blit_rect_mask an image: invalid mask Image object.");
3160
int dsize = data.size();
3161
int srcdsize = p_src->data.size();
3162
int maskdsize = p_mask->data.size();
3163
ERR_FAIL_COND(dsize == 0);
3164
ERR_FAIL_COND(srcdsize == 0);
3165
ERR_FAIL_COND(maskdsize == 0);
3166
ERR_FAIL_COND_MSG(p_src->width != p_mask->width, "Source image width is different from mask width.");
3167
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
3168
ERR_FAIL_COND(format != p_src->format);
3169
3170
Rect2i src_rect;
3171
Rect2i dest_rect;
3172
_get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
3173
if (!src_rect.has_area() || !dest_rect.has_area()) {
3174
return;
3175
}
3176
3177
uint8_t *wp = data.ptrw();
3178
uint8_t *dst_data_ptr = wp;
3179
3180
const uint8_t *rp = p_src->data.ptr();
3181
const uint8_t *src_data_ptr = rp;
3182
3183
int pixel_size = get_format_pixel_size(format);
3184
3185
Ref<Image> msk = p_mask;
3186
3187
for (int i = 0; i < dest_rect.size.y; i++) {
3188
for (int j = 0; j < dest_rect.size.x; j++) {
3189
int src_x = src_rect.position.x + j;
3190
int src_y = src_rect.position.y + i;
3191
3192
if (msk->get_pixel(src_x, src_y).a != 0) {
3193
int dst_x = dest_rect.position.x + j;
3194
int dst_y = dest_rect.position.y + i;
3195
3196
const uint8_t *src = &src_data_ptr[(src_y * p_src->width + src_x) * pixel_size];
3197
uint8_t *dst = &dst_data_ptr[(dst_y * width + dst_x) * pixel_size];
3198
3199
for (int k = 0; k < pixel_size; k++) {
3200
dst[k] = src[k];
3201
}
3202
}
3203
}
3204
}
3205
}
3206
3207
void Image::blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
3208
ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blend_rect an image: invalid source Image object.");
3209
int dsize = data.size();
3210
int srcdsize = p_src->data.size();
3211
ERR_FAIL_COND(dsize == 0);
3212
ERR_FAIL_COND(srcdsize == 0);
3213
ERR_FAIL_COND(format != p_src->format);
3214
3215
Rect2i src_rect;
3216
Rect2i dest_rect;
3217
_get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
3218
if (!src_rect.has_area() || !dest_rect.has_area()) {
3219
return;
3220
}
3221
3222
Ref<Image> img = p_src;
3223
3224
for (int i = 0; i < dest_rect.size.y; i++) {
3225
for (int j = 0; j < dest_rect.size.x; j++) {
3226
int src_x = src_rect.position.x + j;
3227
int src_y = src_rect.position.y + i;
3228
3229
int dst_x = dest_rect.position.x + j;
3230
int dst_y = dest_rect.position.y + i;
3231
3232
Color sc = img->get_pixel(src_x, src_y);
3233
if (sc.a != 0) {
3234
Color dc = get_pixel(dst_x, dst_y);
3235
dc = dc.blend(sc);
3236
set_pixel(dst_x, dst_y, dc);
3237
}
3238
}
3239
}
3240
}
3241
3242
void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
3243
ERR_FAIL_COND_MSG(p_src.is_null(), "Cannot blend_rect_mask an image: invalid source Image object.");
3244
ERR_FAIL_COND_MSG(p_mask.is_null(), "Cannot blend_rect_mask an image: invalid mask Image object.");
3245
int dsize = data.size();
3246
int srcdsize = p_src->data.size();
3247
int maskdsize = p_mask->data.size();
3248
ERR_FAIL_COND(dsize == 0);
3249
ERR_FAIL_COND(srcdsize == 0);
3250
ERR_FAIL_COND(maskdsize == 0);
3251
ERR_FAIL_COND_MSG(p_src->width != p_mask->width, "Source image width is different from mask width.");
3252
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
3253
ERR_FAIL_COND(format != p_src->format);
3254
3255
Rect2i src_rect;
3256
Rect2i dest_rect;
3257
_get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
3258
if (!src_rect.has_area() || !dest_rect.has_area()) {
3259
return;
3260
}
3261
3262
Ref<Image> img = p_src;
3263
Ref<Image> msk = p_mask;
3264
3265
for (int i = 0; i < dest_rect.size.y; i++) {
3266
for (int j = 0; j < dest_rect.size.x; j++) {
3267
int src_x = src_rect.position.x + j;
3268
int src_y = src_rect.position.y + i;
3269
3270
// If the mask's pixel is transparent then we skip it
3271
//Color c = msk->get_pixel(src_x, src_y);
3272
//if (c.a == 0) continue;
3273
if (msk->get_pixel(src_x, src_y).a != 0) {
3274
int dst_x = dest_rect.position.x + j;
3275
int dst_y = dest_rect.position.y + i;
3276
3277
Color sc = img->get_pixel(src_x, src_y);
3278
if (sc.a != 0) {
3279
Color dc = get_pixel(dst_x, dst_y);
3280
dc = dc.blend(sc);
3281
set_pixel(dst_x, dst_y, dc);
3282
}
3283
}
3284
}
3285
}
3286
}
3287
3288
// Repeats `p_pixel` `p_count` times in consecutive memory.
3289
// Results in the original pixel and `p_count - 1` subsequent copies of it.
3290
void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count) {
3291
int offset = 1;
3292
for (int stride = 1; offset + stride <= p_count; stride *= 2) {
3293
memcpy(p_pixel + offset * p_pixel_size, p_pixel, stride * p_pixel_size);
3294
offset += stride;
3295
}
3296
if (offset < p_count) {
3297
memcpy(p_pixel + offset * p_pixel_size, p_pixel, (p_count - offset) * p_pixel_size);
3298
}
3299
}
3300
3301
void Image::fill(const Color &p_color) {
3302
if (data.is_empty()) {
3303
return;
3304
}
3305
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
3306
3307
uint8_t *dst_data_ptr = data.ptrw();
3308
int pixel_size = get_format_pixel_size(format);
3309
int64_t pixel_count = data.size() / pixel_size;
3310
3311
// Put first pixel with the format-aware API.
3312
_set_color_at_ofs(dst_data_ptr, 0, p_color);
3313
3314
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, pixel_count);
3315
}
3316
3317
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
3318
if (data.is_empty()) {
3319
return;
3320
}
3321
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill rect in compressed image formats.");
3322
3323
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs());
3324
if (!r.has_area()) {
3325
return;
3326
}
3327
3328
uint8_t *dst_data_ptr = data.ptrw();
3329
3330
int pixel_size = get_format_pixel_size(format);
3331
3332
// Put first pixel with the format-aware API.
3333
uint8_t *rect_first_pixel_ptr = &dst_data_ptr[(r.position.y * width + r.position.x) * pixel_size];
3334
_set_color_at_ofs(rect_first_pixel_ptr, 0, p_color);
3335
3336
if (r.size.x == width) {
3337
// No need to fill rows separately.
3338
_repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, width * r.size.y);
3339
} else {
3340
_repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, r.size.x);
3341
for (int y = 1; y < r.size.y; y++) {
3342
memcpy(rect_first_pixel_ptr + y * width * pixel_size, rect_first_pixel_ptr, r.size.x * pixel_size);
3343
}
3344
}
3345
}
3346
3347
void Image::_set_data(const Dictionary &p_data) {
3348
ERR_FAIL_COND(!p_data.has("width"));
3349
ERR_FAIL_COND(!p_data.has("height"));
3350
ERR_FAIL_COND(!p_data.has("format"));
3351
ERR_FAIL_COND(!p_data.has("mipmaps"));
3352
ERR_FAIL_COND(!p_data.has("data"));
3353
3354
int dwidth = p_data["width"];
3355
int dheight = p_data["height"];
3356
String dformat = p_data["format"];
3357
bool dmipmaps = p_data["mipmaps"];
3358
Vector<uint8_t> ddata = p_data["data"];
3359
Format ddformat = FORMAT_MAX;
3360
for (int i = 0; i < FORMAT_MAX; i++) {
3361
if (dformat == get_format_name(Format(i))) {
3362
ddformat = Format(i);
3363
break;
3364
}
3365
}
3366
3367
ERR_FAIL_COND(ddformat == FORMAT_MAX);
3368
3369
initialize_data(dwidth, dheight, dmipmaps, ddformat, ddata);
3370
}
3371
3372
Dictionary Image::_get_data() const {
3373
Dictionary d;
3374
d["width"] = width;
3375
d["height"] = height;
3376
d["format"] = get_format_name(format);
3377
d["mipmaps"] = mipmaps;
3378
d["data"] = data;
3379
return d;
3380
}
3381
3382
Color Image::get_pixelv(const Point2i &p_point) const {
3383
return get_pixel(p_point.x, p_point.y);
3384
}
3385
3386
void Image::_copy_internals_from(const Image &p_image) {
3387
format = p_image.format;
3388
width = p_image.width;
3389
height = p_image.height;
3390
mipmaps = p_image.mipmaps;
3391
data = p_image.data;
3392
}
3393
3394
_FORCE_INLINE_ Color color_from_rgba4444(uint16_t p_col) {
3395
float r = ((p_col >> 12) & 0xF) / 15.0;
3396
float g = ((p_col >> 8) & 0xF) / 15.0;
3397
float b = ((p_col >> 4) & 0xF) / 15.0;
3398
float a = (p_col & 0xF) / 15.0;
3399
return Color(r, g, b, a);
3400
}
3401
3402
_FORCE_INLINE_ uint16_t color_to_rgba4444(Color p_col) {
3403
uint16_t rgba = 0;
3404
3405
rgba = uint16_t(CLAMP(p_col.r * 15.0, 0, 15)) << 12;
3406
rgba |= uint16_t(CLAMP(p_col.g * 15.0, 0, 15)) << 8;
3407
rgba |= uint16_t(CLAMP(p_col.b * 15.0, 0, 15)) << 4;
3408
rgba |= uint16_t(CLAMP(p_col.a * 15.0, 0, 15));
3409
3410
return rgba;
3411
}
3412
3413
_FORCE_INLINE_ Color color_from_rgb565(uint16_t p_col) {
3414
float r = ((p_col >> 11) & 0x1F) / 31.0;
3415
float g = ((p_col >> 5) & 0x3F) / 63.0;
3416
float b = (p_col & 0x1F) / 31.0;
3417
return Color(r, g, b, 1.0);
3418
}
3419
3420
_FORCE_INLINE_ uint16_t color_to_rgb565(Color p_col) {
3421
uint16_t rgba = 0;
3422
3423
rgba = uint16_t(CLAMP(p_col.r * 31.0, 0, 31)) << 11;
3424
rgba |= uint16_t(CLAMP(p_col.g * 63.0, 0, 63)) << 5;
3425
rgba |= uint16_t(CLAMP(p_col.b * 31.0, 0, 31));
3426
3427
return rgba;
3428
}
3429
3430
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
3431
switch (format) {
3432
case FORMAT_L8: {
3433
float l = ptr[ofs] / 255.0;
3434
return Color(l, l, l, 1);
3435
}
3436
case FORMAT_LA8: {
3437
float l = ptr[ofs * 2 + 0] / 255.0;
3438
float a = ptr[ofs * 2 + 1] / 255.0;
3439
return Color(l, l, l, a);
3440
}
3441
case FORMAT_R8: {
3442
float r = ptr[ofs] / 255.0;
3443
return Color(r, 0, 0, 1);
3444
}
3445
case FORMAT_RG8: {
3446
float r = ptr[ofs * 2 + 0] / 255.0;
3447
float g = ptr[ofs * 2 + 1] / 255.0;
3448
return Color(r, g, 0, 1);
3449
}
3450
case FORMAT_RGB8: {
3451
float r = ptr[ofs * 3 + 0] / 255.0;
3452
float g = ptr[ofs * 3 + 1] / 255.0;
3453
float b = ptr[ofs * 3 + 2] / 255.0;
3454
return Color(r, g, b, 1);
3455
}
3456
case FORMAT_RGBA8: {
3457
float r = ptr[ofs * 4 + 0] / 255.0;
3458
float g = ptr[ofs * 4 + 1] / 255.0;
3459
float b = ptr[ofs * 4 + 2] / 255.0;
3460
float a = ptr[ofs * 4 + 3] / 255.0;
3461
return Color(r, g, b, a);
3462
}
3463
case FORMAT_RGBA4444: {
3464
return color_from_rgba4444(((uint16_t *)ptr)[ofs]);
3465
}
3466
case FORMAT_RGB565: {
3467
return color_from_rgb565(((uint16_t *)ptr)[ofs]);
3468
}
3469
case FORMAT_RF: {
3470
float r = ((float *)ptr)[ofs];
3471
return Color(r, 0, 0, 1);
3472
}
3473
case FORMAT_RGF: {
3474
float r = ((float *)ptr)[ofs * 2 + 0];
3475
float g = ((float *)ptr)[ofs * 2 + 1];
3476
return Color(r, g, 0, 1);
3477
}
3478
case FORMAT_RGBF: {
3479
float r = ((float *)ptr)[ofs * 3 + 0];
3480
float g = ((float *)ptr)[ofs * 3 + 1];
3481
float b = ((float *)ptr)[ofs * 3 + 2];
3482
return Color(r, g, b, 1);
3483
}
3484
case FORMAT_RGBAF: {
3485
float r = ((float *)ptr)[ofs * 4 + 0];
3486
float g = ((float *)ptr)[ofs * 4 + 1];
3487
float b = ((float *)ptr)[ofs * 4 + 2];
3488
float a = ((float *)ptr)[ofs * 4 + 3];
3489
return Color(r, g, b, a);
3490
}
3491
case FORMAT_RH: {
3492
uint16_t r = ((uint16_t *)ptr)[ofs];
3493
return Color(Math::half_to_float(r), 0, 0, 1);
3494
}
3495
case FORMAT_RGH: {
3496
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
3497
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
3498
return Color(Math::half_to_float(r), Math::half_to_float(g), 0, 1);
3499
}
3500
case FORMAT_RGBH: {
3501
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
3502
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
3503
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
3504
return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), 1);
3505
}
3506
case FORMAT_RGBAH: {
3507
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
3508
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
3509
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
3510
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
3511
return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), Math::half_to_float(a));
3512
}
3513
case FORMAT_RGBE9995: {
3514
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
3515
}
3516
case FORMAT_R16: {
3517
float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
3518
return Color(r, 0, 0, 1);
3519
}
3520
case FORMAT_RG16: {
3521
float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
3522
float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
3523
return Color(r, g, 0, 1);
3524
}
3525
case FORMAT_RGB16: {
3526
float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
3527
float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
3528
float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
3529
return Color(r, g, b, 1);
3530
}
3531
case FORMAT_RGBA16: {
3532
float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
3533
float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
3534
float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
3535
float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
3536
return Color(r, g, b, a);
3537
}
3538
case FORMAT_R16I: {
3539
uint16_t r = ((uint16_t *)ptr)[ofs];
3540
return Color(r, 0, 0, 1);
3541
}
3542
case FORMAT_RG16I: {
3543
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
3544
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
3545
return Color(r, g, 0, 1);
3546
}
3547
case FORMAT_RGB16I: {
3548
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
3549
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
3550
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
3551
return Color(r, g, b, 1);
3552
}
3553
case FORMAT_RGBA16I: {
3554
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
3555
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
3556
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
3557
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
3558
return Color(r, g, b, a);
3559
}
3560
3561
default: {
3562
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
3563
}
3564
}
3565
}
3566
3567
void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) {
3568
switch (format) {
3569
case FORMAT_L8: {
3570
ptr[ofs] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255));
3571
} break;
3572
case FORMAT_LA8: {
3573
ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255));
3574
ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
3575
} break;
3576
case FORMAT_R8: {
3577
ptr[ofs] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
3578
} break;
3579
case FORMAT_RG8: {
3580
ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
3581
ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255));
3582
} break;
3583
case FORMAT_RGB8: {
3584
ptr[ofs * 3 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
3585
ptr[ofs * 3 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255));
3586
ptr[ofs * 3 + 2] = uint8_t(CLAMP(p_color.b * 255.0, 0, 255));
3587
} break;
3588
case FORMAT_RGBA8: {
3589
ptr[ofs * 4 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
3590
ptr[ofs * 4 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255));
3591
ptr[ofs * 4 + 2] = uint8_t(CLAMP(p_color.b * 255.0, 0, 255));
3592
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
3593
} break;
3594
case FORMAT_RGBA4444: {
3595
((uint16_t *)ptr)[ofs] = color_to_rgba4444(p_color);
3596
} break;
3597
case FORMAT_RGB565: {
3598
((uint16_t *)ptr)[ofs] = color_to_rgb565(p_color);
3599
} break;
3600
case FORMAT_RF: {
3601
((float *)ptr)[ofs] = p_color.r;
3602
} break;
3603
case FORMAT_RGF: {
3604
((float *)ptr)[ofs * 2 + 0] = p_color.r;
3605
((float *)ptr)[ofs * 2 + 1] = p_color.g;
3606
} break;
3607
case FORMAT_RGBF: {
3608
((float *)ptr)[ofs * 3 + 0] = p_color.r;
3609
((float *)ptr)[ofs * 3 + 1] = p_color.g;
3610
((float *)ptr)[ofs * 3 + 2] = p_color.b;
3611
} break;
3612
case FORMAT_RGBAF: {
3613
((float *)ptr)[ofs * 4 + 0] = p_color.r;
3614
((float *)ptr)[ofs * 4 + 1] = p_color.g;
3615
((float *)ptr)[ofs * 4 + 2] = p_color.b;
3616
((float *)ptr)[ofs * 4 + 3] = p_color.a;
3617
} break;
3618
case FORMAT_RH: {
3619
((uint16_t *)ptr)[ofs] = Math::make_half_float(p_color.r);
3620
} break;
3621
case FORMAT_RGH: {
3622
((uint16_t *)ptr)[ofs * 2 + 0] = Math::make_half_float(p_color.r);
3623
((uint16_t *)ptr)[ofs * 2 + 1] = Math::make_half_float(p_color.g);
3624
} break;
3625
case FORMAT_RGBH: {
3626
((uint16_t *)ptr)[ofs * 3 + 0] = Math::make_half_float(p_color.r);
3627
((uint16_t *)ptr)[ofs * 3 + 1] = Math::make_half_float(p_color.g);
3628
((uint16_t *)ptr)[ofs * 3 + 2] = Math::make_half_float(p_color.b);
3629
} break;
3630
case FORMAT_RGBAH: {
3631
((uint16_t *)ptr)[ofs * 4 + 0] = Math::make_half_float(p_color.r);
3632
((uint16_t *)ptr)[ofs * 4 + 1] = Math::make_half_float(p_color.g);
3633
((uint16_t *)ptr)[ofs * 4 + 2] = Math::make_half_float(p_color.b);
3634
((uint16_t *)ptr)[ofs * 4 + 3] = Math::make_half_float(p_color.a);
3635
} break;
3636
case FORMAT_RGBE9995: {
3637
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
3638
} break;
3639
case FORMAT_R16: {
3640
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
3641
} break;
3642
case FORMAT_RG16: {
3643
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
3644
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
3645
} break;
3646
case FORMAT_RGB16: {
3647
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
3648
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
3649
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
3650
} break;
3651
case FORMAT_RGBA16: {
3652
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
3653
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
3654
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
3655
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
3656
} break;
3657
case FORMAT_R16I: {
3658
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
3659
} break;
3660
case FORMAT_RG16I: {
3661
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
3662
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
3663
} break;
3664
case FORMAT_RGB16I: {
3665
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
3666
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
3667
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
3668
} break;
3669
case FORMAT_RGBA16I: {
3670
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
3671
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
3672
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
3673
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
3674
} break;
3675
3676
default: {
3677
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
3678
}
3679
}
3680
}
3681
3682
Color Image::get_pixel(int p_x, int p_y) const {
3683
#ifdef DEBUG_ENABLED
3684
ERR_FAIL_INDEX_V(p_x, width, Color());
3685
ERR_FAIL_INDEX_V(p_y, height, Color());
3686
#endif
3687
3688
uint32_t ofs = p_y * width + p_x;
3689
return _get_color_at_ofs(data.ptr(), ofs);
3690
}
3691
3692
void Image::set_pixelv(const Point2i &p_point, const Color &p_color) {
3693
set_pixel(p_point.x, p_point.y, p_color);
3694
}
3695
3696
void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
3697
#ifdef DEBUG_ENABLED
3698
ERR_FAIL_INDEX(p_x, width);
3699
ERR_FAIL_INDEX(p_y, height);
3700
#endif
3701
3702
uint32_t ofs = p_y * width + p_x;
3703
_set_color_at_ofs(data.ptrw(), ofs, p_color);
3704
}
3705
3706
const uint8_t *Image::ptr() const {
3707
return data.ptr();
3708
}
3709
3710
uint8_t *Image::ptrw() {
3711
return data.ptrw();
3712
}
3713
3714
int64_t Image::get_data_size() const {
3715
return data.size();
3716
}
3717
3718
void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) {
3719
ERR_FAIL_COND_MSG(is_compressed(), "Cannot adjust_bcs in compressed image formats.");
3720
3721
uint8_t *w = data.ptrw();
3722
uint32_t pixel_size = get_format_pixel_size(format);
3723
uint32_t pixel_count = data.size() / pixel_size;
3724
3725
for (uint32_t i = 0; i < pixel_count; i++) {
3726
Color c = _get_color_at_ofs(w, i);
3727
Vector3 rgb(c.r, c.g, c.b);
3728
3729
rgb *= p_brightness;
3730
rgb = Vector3(0.5, 0.5, 0.5).lerp(rgb, p_contrast);
3731
float center = (rgb.x + rgb.y + rgb.z) / 3.0;
3732
rgb = Vector3(center, center, center).lerp(rgb, p_saturation);
3733
c.r = rgb.x;
3734
c.g = rgb.y;
3735
c.b = rgb.z;
3736
_set_color_at_ofs(w, i, c);
3737
}
3738
}
3739
3740
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
3741
ERR_FAIL_COND_V(data.is_empty(), USED_CHANNELS_RGBA);
3742
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
3743
3744
if (p_source == COMPRESS_SOURCE_NORMAL) {
3745
return USED_CHANNELS_RG; // Normal maps only use RG channels.
3746
}
3747
3748
if (format == FORMAT_L8) {
3749
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
3750
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
3751
return USED_CHANNELS_R; // Red only cannot have any channel less.
3752
}
3753
3754
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
3755
bool r = false, g = false, b = false, a = false, c = false;
3756
3757
const uint8_t *data_ptr = data.ptr();
3758
const uint32_t data_total = width * height;
3759
3760
for (uint32_t i = 0; i < data_total; i++) {
3761
Color col = _get_color_at_ofs(data_ptr, i);
3762
3763
if (!r && col.r > 0.001) {
3764
r = true;
3765
}
3766
if (!g && col.g > 0.001) {
3767
g = true;
3768
}
3769
if (!b && col.b > 0.001) {
3770
b = true;
3771
}
3772
if (!a && col.a < 0.999) {
3773
a = true;
3774
}
3775
3776
if (col.r != col.b || col.r != col.g || col.b != col.g) {
3777
c = true; // The image is not grayscale.
3778
}
3779
3780
if (r && g && b && c) {
3781
// All channels are used, no need to continue.
3782
if (!supports_alpha) {
3783
break;
3784
} else if (a) {
3785
break;
3786
}
3787
}
3788
}
3789
3790
UsedChannels used_channels;
3791
3792
if (!c) {
3793
// Uniform RGB (grayscale).
3794
if (a) {
3795
used_channels = USED_CHANNELS_LA;
3796
} else {
3797
used_channels = USED_CHANNELS_L;
3798
}
3799
} else {
3800
// Colored image.
3801
if (a) {
3802
used_channels = USED_CHANNELS_RGBA;
3803
} else if (b) {
3804
used_channels = USED_CHANNELS_RGB;
3805
} else if (g) {
3806
used_channels = USED_CHANNELS_RG;
3807
} else {
3808
used_channels = USED_CHANNELS_R;
3809
}
3810
}
3811
3812
if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) {
3813
used_channels = USED_CHANNELS_RGB; // R and RG do not support SRGB.
3814
}
3815
3816
return used_channels;
3817
}
3818
3819
void Image::optimize_channels() {
3820
switch (detect_used_channels()) {
3821
case USED_CHANNELS_L:
3822
convert(FORMAT_L8);
3823
break;
3824
case USED_CHANNELS_LA:
3825
convert(FORMAT_LA8);
3826
break;
3827
case USED_CHANNELS_R:
3828
convert(FORMAT_R8);
3829
break;
3830
case USED_CHANNELS_RG:
3831
convert(FORMAT_RG8);
3832
break;
3833
case USED_CHANNELS_RGB:
3834
convert(FORMAT_RGB8);
3835
break;
3836
case USED_CHANNELS_RGBA:
3837
convert(FORMAT_RGBA8);
3838
break;
3839
}
3840
}
3841
3842
void Image::_bind_methods() {
3843
ClassDB::bind_method(D_METHOD("get_width"), &Image::get_width);
3844
ClassDB::bind_method(D_METHOD("get_height"), &Image::get_height);
3845
ClassDB::bind_method(D_METHOD("get_size"), &Image::get_size);
3846
ClassDB::bind_method(D_METHOD("has_mipmaps"), &Image::has_mipmaps);
3847
ClassDB::bind_method(D_METHOD("get_format"), &Image::get_format);
3848
ClassDB::bind_method(D_METHOD("get_data"), &Image::get_data);
3849
ClassDB::bind_method(D_METHOD("get_data_size"), &Image::get_data_size);
3850
3851
ClassDB::bind_method(D_METHOD("convert", "format"), &Image::convert);
3852
3853
ClassDB::bind_method(D_METHOD("get_mipmap_count"), &Image::get_mipmap_count);
3854
ClassDB::bind_method(D_METHOD("get_mipmap_offset", "mipmap"), &Image::get_mipmap_offset);
3855
3856
ClassDB::bind_method(D_METHOD("resize_to_po2", "square", "interpolation"), &Image::resize_to_po2, DEFVAL(false), DEFVAL(INTERPOLATE_BILINEAR));
3857
ClassDB::bind_method(D_METHOD("resize", "width", "height", "interpolation"), &Image::resize, DEFVAL(INTERPOLATE_BILINEAR));
3858
ClassDB::bind_method(D_METHOD("shrink_x2"), &Image::shrink_x2);
3859
3860
ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);
3861
ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);
3862
ClassDB::bind_method(D_METHOD("flip_y"), &Image::flip_y);
3863
ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false));
3864
ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps);
3865
3866
#ifndef DISABLE_DEPRECATED
3867
ClassDB::bind_static_method("Image", D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::create_empty);
3868
#endif
3869
ClassDB::bind_static_method("Image", D_METHOD("create_empty", "width", "height", "use_mipmaps", "format"), &Image::create_empty);
3870
ClassDB::bind_static_method("Image", D_METHOD("create_from_data", "width", "height", "use_mipmaps", "format", "data"), &Image::create_from_data);
3871
ClassDB::bind_method(D_METHOD("set_data", "width", "height", "use_mipmaps", "format", "data"), &Image::set_data);
3872
3873
ClassDB::bind_method(D_METHOD("is_empty"), &Image::is_empty);
3874
3875
ClassDB::bind_method(D_METHOD("load", "path"), &Image::load);
3876
ClassDB::bind_static_method("Image", D_METHOD("load_from_file", "path"), &Image::load_from_file);
3877
ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png);
3878
ClassDB::bind_method(D_METHOD("save_png_to_buffer"), &Image::save_png_to_buffer);
3879
ClassDB::bind_method(D_METHOD("save_jpg", "path", "quality"), &Image::save_jpg, DEFVAL(0.75));
3880
ClassDB::bind_method(D_METHOD("save_jpg_to_buffer", "quality"), &Image::save_jpg_to_buffer, DEFVAL(0.75));
3881
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
3882
ClassDB::bind_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::save_exr_to_buffer, DEFVAL(false));
3883
ClassDB::bind_method(D_METHOD("save_dds", "path"), &Image::save_dds);
3884
ClassDB::bind_method(D_METHOD("save_dds_to_buffer"), &Image::save_dds_to_buffer);
3885
3886
ClassDB::bind_method(D_METHOD("save_webp", "path", "lossy", "quality"), &Image::save_webp, DEFVAL(false), DEFVAL(0.75f));
3887
ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f));
3888
3889
ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha);
3890
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);
3891
3892
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
3893
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4));
3894
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::compress_from_channels, DEFVAL(ASTC_FORMAT_4x4));
3895
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
3896
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
3897
3898
ClassDB::bind_method(D_METHOD("rotate_90", "direction"), &Image::rotate_90);
3899
ClassDB::bind_method(D_METHOD("rotate_180"), &Image::rotate_180);
3900
3901
ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges);
3902
ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
3903
ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
3904
ClassDB::bind_method(D_METHOD("linear_to_srgb"), &Image::linear_to_srgb);
3905
ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy);
3906
ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb);
3907
ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0));
3908
3909
ClassDB::bind_method(D_METHOD("compute_image_metrics", "compared_image", "use_luma"), &Image::compute_image_metrics);
3910
3911
ClassDB::bind_method(D_METHOD("blit_rect", "src", "src_rect", "dst"), &Image::blit_rect);
3912
ClassDB::bind_method(D_METHOD("blit_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blit_rect_mask);
3913
ClassDB::bind_method(D_METHOD("blend_rect", "src", "src_rect", "dst"), &Image::blend_rect);
3914
ClassDB::bind_method(D_METHOD("blend_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blend_rect_mask);
3915
ClassDB::bind_method(D_METHOD("fill", "color"), &Image::fill);
3916
ClassDB::bind_method(D_METHOD("fill_rect", "rect", "color"), &Image::fill_rect);
3917
3918
ClassDB::bind_method(D_METHOD("get_used_rect"), &Image::get_used_rect);
3919
ClassDB::bind_method(D_METHOD("get_region", "region"), &Image::get_region);
3920
3921
ClassDB::bind_method(D_METHOD("copy_from", "src"), &Image::copy_internals_from);
3922
3923
ClassDB::bind_method(D_METHOD("_set_data", "data"), &Image::_set_data);
3924
ClassDB::bind_method(D_METHOD("_get_data"), &Image::_get_data);
3925
3926
ClassDB::bind_method(D_METHOD("get_pixelv", "point"), &Image::get_pixelv);
3927
ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel);
3928
ClassDB::bind_method(D_METHOD("set_pixelv", "point", "color"), &Image::set_pixelv);
3929
ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel);
3930
3931
ClassDB::bind_method(D_METHOD("adjust_bcs", "brightness", "contrast", "saturation"), &Image::adjust_bcs);
3932
3933
ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer);
3934
ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer);
3935
ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer);
3936
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
3937
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
3938
ClassDB::bind_method(D_METHOD("load_ktx_from_buffer", "buffer"), &Image::load_ktx_from_buffer);
3939
ClassDB::bind_method(D_METHOD("load_dds_from_buffer", "buffer"), &Image::load_dds_from_buffer);
3940
ClassDB::bind_method(D_METHOD("load_exr_from_buffer", "buffer"), &Image::load_exr_from_buffer);
3941
3942
ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
3943
ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
3944
3945
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
3946
3947
BIND_CONSTANT(MAX_WIDTH);
3948
BIND_CONSTANT(MAX_HEIGHT);
3949
3950
BIND_ENUM_CONSTANT(FORMAT_L8);
3951
BIND_ENUM_CONSTANT(FORMAT_LA8);
3952
BIND_ENUM_CONSTANT(FORMAT_R8);
3953
BIND_ENUM_CONSTANT(FORMAT_RG8);
3954
BIND_ENUM_CONSTANT(FORMAT_RGB8);
3955
BIND_ENUM_CONSTANT(FORMAT_RGBA8);
3956
BIND_ENUM_CONSTANT(FORMAT_RGBA4444);
3957
BIND_ENUM_CONSTANT(FORMAT_RGB565);
3958
BIND_ENUM_CONSTANT(FORMAT_RF);
3959
BIND_ENUM_CONSTANT(FORMAT_RGF);
3960
BIND_ENUM_CONSTANT(FORMAT_RGBF);
3961
BIND_ENUM_CONSTANT(FORMAT_RGBAF);
3962
BIND_ENUM_CONSTANT(FORMAT_RH);
3963
BIND_ENUM_CONSTANT(FORMAT_RGH);
3964
BIND_ENUM_CONSTANT(FORMAT_RGBH);
3965
BIND_ENUM_CONSTANT(FORMAT_RGBAH);
3966
BIND_ENUM_CONSTANT(FORMAT_RGBE9995);
3967
BIND_ENUM_CONSTANT(FORMAT_DXT1);
3968
BIND_ENUM_CONSTANT(FORMAT_DXT3);
3969
BIND_ENUM_CONSTANT(FORMAT_DXT5);
3970
BIND_ENUM_CONSTANT(FORMAT_RGTC_R);
3971
BIND_ENUM_CONSTANT(FORMAT_RGTC_RG);
3972
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA);
3973
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF);
3974
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU);
3975
BIND_ENUM_CONSTANT(FORMAT_ETC);
3976
BIND_ENUM_CONSTANT(FORMAT_ETC2_R11);
3977
BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S);
3978
BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11);
3979
BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11S);
3980
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8);
3981
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGBA8);
3982
BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8A1);
3983
BIND_ENUM_CONSTANT(FORMAT_ETC2_RA_AS_RG);
3984
BIND_ENUM_CONSTANT(FORMAT_DXT5_RA_AS_RG);
3985
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4);
3986
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
3987
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
3988
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
3989
BIND_ENUM_CONSTANT(FORMAT_R16);
3990
BIND_ENUM_CONSTANT(FORMAT_RG16);
3991
BIND_ENUM_CONSTANT(FORMAT_RGB16);
3992
BIND_ENUM_CONSTANT(FORMAT_RGBA16);
3993
BIND_ENUM_CONSTANT(FORMAT_R16I);
3994
BIND_ENUM_CONSTANT(FORMAT_RG16I);
3995
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
3996
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
3997
BIND_ENUM_CONSTANT(FORMAT_MAX);
3998
3999
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
4000
BIND_ENUM_CONSTANT(INTERPOLATE_BILINEAR);
4001
BIND_ENUM_CONSTANT(INTERPOLATE_CUBIC);
4002
BIND_ENUM_CONSTANT(INTERPOLATE_TRILINEAR);
4003
BIND_ENUM_CONSTANT(INTERPOLATE_LANCZOS);
4004
4005
BIND_ENUM_CONSTANT(ALPHA_NONE);
4006
BIND_ENUM_CONSTANT(ALPHA_BIT);
4007
BIND_ENUM_CONSTANT(ALPHA_BLEND);
4008
4009
BIND_ENUM_CONSTANT(COMPRESS_S3TC);
4010
BIND_ENUM_CONSTANT(COMPRESS_ETC);
4011
BIND_ENUM_CONSTANT(COMPRESS_ETC2);
4012
BIND_ENUM_CONSTANT(COMPRESS_BPTC);
4013
BIND_ENUM_CONSTANT(COMPRESS_ASTC);
4014
BIND_ENUM_CONSTANT(COMPRESS_MAX);
4015
4016
BIND_ENUM_CONSTANT(USED_CHANNELS_L);
4017
BIND_ENUM_CONSTANT(USED_CHANNELS_LA);
4018
BIND_ENUM_CONSTANT(USED_CHANNELS_R);
4019
BIND_ENUM_CONSTANT(USED_CHANNELS_RG);
4020
BIND_ENUM_CONSTANT(USED_CHANNELS_RGB);
4021
BIND_ENUM_CONSTANT(USED_CHANNELS_RGBA);
4022
4023
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC);
4024
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB);
4025
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL);
4026
4027
BIND_ENUM_CONSTANT(ASTC_FORMAT_4x4);
4028
BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
4029
}
4030
4031
void Image::normal_map_to_xy() {
4032
convert(Image::FORMAT_RGBA8);
4033
4034
{
4035
int len = data.size() / 4;
4036
uint8_t *data_ptr = data.ptrw();
4037
4038
for (int i = 0; i < len; i++) {
4039
data_ptr[(i << 2) + 3] = data_ptr[(i << 2) + 0]; //x to w
4040
data_ptr[(i << 2) + 0] = data_ptr[(i << 2) + 1]; //y to xz
4041
data_ptr[(i << 2) + 2] = data_ptr[(i << 2) + 1];
4042
}
4043
}
4044
4045
convert(Image::FORMAT_LA8);
4046
}
4047
4048
Ref<Image> Image::rgbe_to_srgb() {
4049
if (data.is_empty()) {
4050
return Ref<Image>();
4051
}
4052
4053
ERR_FAIL_COND_V(format != FORMAT_RGBE9995, Ref<Image>());
4054
4055
Ref<Image> new_image = create_empty(width, height, false, Image::FORMAT_RGB8);
4056
4057
for (int row = 0; row < height; row++) {
4058
for (int col = 0; col < width; col++) {
4059
new_image->set_pixel(col, row, get_pixel(col, row).linear_to_srgb());
4060
}
4061
}
4062
4063
if (has_mipmaps()) {
4064
new_image->generate_mipmaps();
4065
}
4066
4067
return new_image;
4068
}
4069
4070
Ref<Image> Image::get_image_from_mipmap(int p_mipmap) const {
4071
int64_t ofs, size;
4072
int w, h;
4073
get_mipmap_offset_size_and_dimensions(p_mipmap, ofs, size, w, h);
4074
4075
Vector<uint8_t> new_data;
4076
new_data.resize(size);
4077
4078
{
4079
uint8_t *wr = new_data.ptrw();
4080
const uint8_t *rd = data.ptr();
4081
memcpy(wr, rd + ofs, size);
4082
}
4083
4084
Ref<Image> image;
4085
image.instantiate();
4086
image->width = w;
4087
image->height = h;
4088
image->format = format;
4089
image->data = new_data;
4090
4091
image->mipmaps = false;
4092
return image;
4093
}
4094
4095
void Image::bump_map_to_normal_map(float bump_scale) {
4096
ERR_FAIL_COND(is_compressed());
4097
clear_mipmaps();
4098
convert(Image::FORMAT_RF);
4099
4100
Vector<uint8_t> result_image; //rgba output
4101
result_image.resize(width * height * 4);
4102
4103
{
4104
const uint8_t *rp = data.ptr();
4105
uint8_t *wp = result_image.ptrw();
4106
4107
ERR_FAIL_NULL(rp);
4108
4109
unsigned char *write_ptr = wp;
4110
float *read_ptr = (float *)rp;
4111
4112
for (int ty = 0; ty < height; ty++) {
4113
int py = ty + 1;
4114
if (py >= height) {
4115
py -= height;
4116
}
4117
4118
for (int tx = 0; tx < width; tx++) {
4119
int px = tx + 1;
4120
if (px >= width) {
4121
px -= width;
4122
}
4123
float here = read_ptr[ty * width + tx];
4124
float to_right = read_ptr[ty * width + px];
4125
float above = read_ptr[py * width + tx];
4126
Vector3 up = Vector3(0, 1, (here - above) * bump_scale);
4127
Vector3 across = Vector3(1, 0, (to_right - here) * bump_scale);
4128
4129
Vector3 normal = across.cross(up);
4130
normal.normalize();
4131
4132
write_ptr[((ty * width + tx) << 2) + 0] = (127.5 + normal.x * 127.5);
4133
write_ptr[((ty * width + tx) << 2) + 1] = (127.5 + normal.y * 127.5);
4134
write_ptr[((ty * width + tx) << 2) + 2] = (127.5 + normal.z * 127.5);
4135
write_ptr[((ty * width + tx) << 2) + 3] = 255;
4136
}
4137
}
4138
}
4139
format = FORMAT_RGBA8;
4140
data = result_image;
4141
}
4142
4143
bool Image::detect_signed(bool p_include_mips) const {
4144
ERR_FAIL_COND_V(is_compressed(), false);
4145
4146
if (format >= Image::FORMAT_RH && format <= Image::FORMAT_RGBAH) {
4147
const uint16_t *img_data = reinterpret_cast<const uint16_t *>(data.ptr());
4148
const uint64_t img_size = p_include_mips ? (data.size() / 2) : (width * height * get_format_pixel_size(format) / 2);
4149
4150
for (uint64_t i = 0; i < img_size; i++) {
4151
if ((img_data[i] & 0x8000) != 0 && (img_data[i] & 0x7fff) != 0) {
4152
return true;
4153
}
4154
}
4155
4156
} else if (format >= Image::FORMAT_RF && format <= Image::FORMAT_RGBAF) {
4157
const uint32_t *img_data = reinterpret_cast<const uint32_t *>(data.ptr());
4158
const uint64_t img_size = p_include_mips ? (data.size() / 4) : (width * height * get_format_pixel_size(format) / 4);
4159
4160
for (uint64_t i = 0; i < img_size; i++) {
4161
if ((img_data[i] & 0x80000000) != 0 && (img_data[i] & 0x7fffffff) != 0) {
4162
return true;
4163
}
4164
}
4165
}
4166
4167
return false;
4168
}
4169
4170
void Image::srgb_to_linear() {
4171
if (data.is_empty()) {
4172
return;
4173
}
4174
4175
static const uint8_t srgb2lin[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 148, 150, 152, 153, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 188, 190, 192, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 248, 250, 252, 255 };
4176
4177
ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8);
4178
4179
if (format == FORMAT_RGBA8) {
4180
int len = data.size() / 4;
4181
uint8_t *data_ptr = data.ptrw();
4182
4183
for (int i = 0; i < len; i++) {
4184
data_ptr[(i << 2) + 0] = srgb2lin[data_ptr[(i << 2) + 0]];
4185
data_ptr[(i << 2) + 1] = srgb2lin[data_ptr[(i << 2) + 1]];
4186
data_ptr[(i << 2) + 2] = srgb2lin[data_ptr[(i << 2) + 2]];
4187
}
4188
4189
} else if (format == FORMAT_RGB8) {
4190
int len = data.size() / 3;
4191
uint8_t *data_ptr = data.ptrw();
4192
4193
for (int i = 0; i < len; i++) {
4194
data_ptr[(i * 3) + 0] = srgb2lin[data_ptr[(i * 3) + 0]];
4195
data_ptr[(i * 3) + 1] = srgb2lin[data_ptr[(i * 3) + 1]];
4196
data_ptr[(i * 3) + 2] = srgb2lin[data_ptr[(i * 3) + 2]];
4197
}
4198
}
4199
}
4200
4201
void Image::linear_to_srgb() {
4202
if (data.is_empty()) {
4203
return;
4204
}
4205
4206
static const uint8_t lin2srgb[256] = { 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 };
4207
4208
ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8);
4209
4210
if (format == FORMAT_RGBA8) {
4211
int len = data.size() / 4;
4212
uint8_t *data_ptr = data.ptrw();
4213
4214
for (int i = 0; i < len; i++) {
4215
data_ptr[(i << 2) + 0] = lin2srgb[data_ptr[(i << 2) + 0]];
4216
data_ptr[(i << 2) + 1] = lin2srgb[data_ptr[(i << 2) + 1]];
4217
data_ptr[(i << 2) + 2] = lin2srgb[data_ptr[(i << 2) + 2]];
4218
}
4219
4220
} else if (format == FORMAT_RGB8) {
4221
int len = data.size() / 3;
4222
uint8_t *data_ptr = data.ptrw();
4223
4224
for (int i = 0; i < len; i++) {
4225
data_ptr[(i * 3) + 0] = lin2srgb[data_ptr[(i * 3) + 0]];
4226
data_ptr[(i * 3) + 1] = lin2srgb[data_ptr[(i * 3) + 1]];
4227
data_ptr[(i * 3) + 2] = lin2srgb[data_ptr[(i * 3) + 2]];
4228
}
4229
}
4230
}
4231
4232
void Image::premultiply_alpha() {
4233
if (data.is_empty()) {
4234
return;
4235
}
4236
4237
if (format != FORMAT_RGBA8) {
4238
return; //not needed
4239
}
4240
4241
uint8_t *data_ptr = data.ptrw();
4242
4243
for (int i = 0; i < height; i++) {
4244
for (int j = 0; j < width; j++) {
4245
uint8_t *ptr = &data_ptr[(i * width + j) * 4];
4246
4247
ptr[0] = (uint16_t(ptr[0]) * uint16_t(ptr[3]) + 255U) >> 8;
4248
ptr[1] = (uint16_t(ptr[1]) * uint16_t(ptr[3]) + 255U) >> 8;
4249
ptr[2] = (uint16_t(ptr[2]) * uint16_t(ptr[3]) + 255U) >> 8;
4250
}
4251
}
4252
}
4253
4254
void Image::fix_alpha_edges() {
4255
if (data.is_empty()) {
4256
return;
4257
}
4258
4259
if (format != FORMAT_RGBA8) {
4260
return; //not needed
4261
}
4262
4263
Vector<uint8_t> dcopy = data;
4264
const uint8_t *srcptr = dcopy.ptr();
4265
4266
uint8_t *data_ptr = data.ptrw();
4267
4268
const int max_radius = 4;
4269
const int alpha_threshold = 20;
4270
const int max_dist = 0x7FFFFFFF;
4271
4272
for (int i = 0; i < height; i++) {
4273
for (int j = 0; j < width; j++) {
4274
const uint8_t *rptr = &srcptr[(i * width + j) * 4];
4275
uint8_t *wptr = &data_ptr[(i * width + j) * 4];
4276
4277
if (rptr[3] >= alpha_threshold) {
4278
continue;
4279
}
4280
4281
int closest_dist = max_dist;
4282
uint8_t closest_color[3] = { 0 };
4283
4284
int from_x = MAX(0, j - max_radius);
4285
int to_x = MIN(width - 1, j + max_radius);
4286
int from_y = MAX(0, i - max_radius);
4287
int to_y = MIN(height - 1, i + max_radius);
4288
4289
for (int k = from_y; k <= to_y; k++) {
4290
for (int l = from_x; l <= to_x; l++) {
4291
int dy = i - k;
4292
int dx = j - l;
4293
int dist = dy * dy + dx * dx;
4294
if (dist >= closest_dist) {
4295
continue;
4296
}
4297
4298
const uint8_t *rp2 = &srcptr[(k * width + l) << 2];
4299
4300
if (rp2[3] < alpha_threshold) {
4301
continue;
4302
}
4303
4304
closest_dist = dist;
4305
closest_color[0] = rp2[0];
4306
closest_color[1] = rp2[1];
4307
closest_color[2] = rp2[2];
4308
}
4309
}
4310
4311
if (closest_dist != max_dist) {
4312
wptr[0] = closest_color[0];
4313
wptr[1] = closest_color[1];
4314
wptr[2] = closest_color[2];
4315
}
4316
}
4317
}
4318
}
4319
4320
String Image::get_format_name(Format p_format) {
4321
ERR_FAIL_INDEX_V(p_format, FORMAT_MAX, String());
4322
return format_names[p_format];
4323
}
4324
4325
uint32_t Image::get_format_component_mask(Format p_format) {
4326
const uint32_t r = 1;
4327
const uint32_t rg = 3;
4328
const uint32_t rgb = 7;
4329
const uint32_t rgba = 15;
4330
4331
switch (p_format) {
4332
case FORMAT_L8:
4333
return rgb;
4334
case FORMAT_LA8:
4335
return rgba;
4336
case FORMAT_R8:
4337
return r;
4338
case FORMAT_RG8:
4339
return rg;
4340
case FORMAT_RGB8:
4341
return rgb;
4342
case FORMAT_RGBA8:
4343
return rgba;
4344
case FORMAT_RGBA4444:
4345
return rgba;
4346
case FORMAT_RGB565:
4347
return rgb;
4348
case FORMAT_RF:
4349
return r;
4350
case FORMAT_RGF:
4351
return rg;
4352
case FORMAT_RGBF:
4353
return rgb;
4354
case FORMAT_RGBAF:
4355
return rgba;
4356
case FORMAT_RH:
4357
return r;
4358
case FORMAT_RGH:
4359
return rg;
4360
case FORMAT_RGBH:
4361
return rgb;
4362
case FORMAT_RGBAH:
4363
return rgba;
4364
case FORMAT_RGBE9995:
4365
return rgb;
4366
case FORMAT_DXT1:
4367
return rgb;
4368
case FORMAT_DXT3:
4369
return rgba;
4370
case FORMAT_DXT5:
4371
return rgba;
4372
case FORMAT_RGTC_R:
4373
return r;
4374
case FORMAT_RGTC_RG:
4375
return rg;
4376
case FORMAT_BPTC_RGBA:
4377
return rgba;
4378
case FORMAT_BPTC_RGBF:
4379
return rgb;
4380
case FORMAT_BPTC_RGBFU:
4381
return rgb;
4382
case FORMAT_ETC:
4383
return rgb;
4384
case FORMAT_ETC2_R11:
4385
return r;
4386
case FORMAT_ETC2_R11S:
4387
return r;
4388
case FORMAT_ETC2_RG11:
4389
return rg;
4390
case FORMAT_ETC2_RG11S:
4391
return rg;
4392
case FORMAT_ETC2_RGB8:
4393
return rgb;
4394
case FORMAT_ETC2_RGBA8:
4395
return rgba;
4396
case FORMAT_ETC2_RGB8A1:
4397
return rgba;
4398
case FORMAT_ETC2_RA_AS_RG:
4399
return rg;
4400
case FORMAT_DXT5_RA_AS_RG:
4401
return rg;
4402
case FORMAT_ASTC_4x4:
4403
return rgba;
4404
case FORMAT_ASTC_4x4_HDR:
4405
return rgba;
4406
case FORMAT_ASTC_8x8:
4407
return rgba;
4408
case FORMAT_ASTC_8x8_HDR:
4409
return rgba;
4410
case FORMAT_R16:
4411
return r;
4412
case FORMAT_RG16:
4413
return rg;
4414
case FORMAT_RGB16:
4415
return rgb;
4416
case FORMAT_RGBA16:
4417
return rgba;
4418
case FORMAT_R16I:
4419
return r;
4420
case FORMAT_RG16I:
4421
return rg;
4422
case FORMAT_RGB16I:
4423
return rgb;
4424
case FORMAT_RGBA16I:
4425
return rgba;
4426
default:
4427
ERR_PRINT("Unhandled format.");
4428
return rgba;
4429
}
4430
}
4431
4432
Error Image::load_png_from_buffer(const Vector<uint8_t> &p_array) {
4433
return _load_from_buffer(p_array, _png_mem_loader_func);
4434
}
4435
4436
Error Image::load_jpg_from_buffer(const Vector<uint8_t> &p_array) {
4437
return _load_from_buffer(p_array, _jpg_mem_loader_func);
4438
}
4439
4440
Error Image::load_exr_from_buffer(const Vector<uint8_t> &p_array) {
4441
ERR_FAIL_NULL_V_MSG(
4442
_exr_mem_loader_func,
4443
ERR_UNAVAILABLE,
4444
"The TinyEXR module isn't enabled. Recompile the Godot editor or export template binary with the `tinyexr_export_templates=yes` SCons option.");
4445
return _load_from_buffer(p_array, _exr_mem_loader_func);
4446
}
4447
4448
Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) {
4449
return _load_from_buffer(p_array, _webp_mem_loader_func);
4450
}
4451
4452
Error Image::load_tga_from_buffer(const Vector<uint8_t> &p_array) {
4453
ERR_FAIL_NULL_V_MSG(
4454
_tga_mem_loader_func,
4455
ERR_UNAVAILABLE,
4456
"The TGA module isn't enabled. Recompile the Godot editor or export template binary with the `module_tga_enabled=yes` SCons option.");
4457
return _load_from_buffer(p_array, _tga_mem_loader_func);
4458
}
4459
4460
Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) {
4461
ERR_FAIL_NULL_V_MSG(
4462
_bmp_mem_loader_func,
4463
ERR_UNAVAILABLE,
4464
"The BMP module isn't enabled. Recompile the Godot editor or export template binary with the `module_bmp_enabled=yes` SCons option.");
4465
return _load_from_buffer(p_array, _bmp_mem_loader_func);
4466
}
4467
4468
Error Image::load_dds_from_buffer(const Vector<uint8_t> &p_array) {
4469
ERR_FAIL_NULL_V_MSG(
4470
_dds_mem_loader_func,
4471
ERR_UNAVAILABLE,
4472
"The DDS module isn't enabled. Recompile the Godot editor or export template binary with the `module_dds_enabled=yes` SCons option.");
4473
return _load_from_buffer(p_array, _dds_mem_loader_func);
4474
}
4475
4476
Error Image::load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale) {
4477
ERR_FAIL_NULL_V_MSG(
4478
_svg_scalable_mem_loader_func,
4479
ERR_UNAVAILABLE,
4480
"The SVG module isn't enabled. Recompile the Godot editor or export template binary with the `module_svg_enabled=yes` SCons option.");
4481
4482
int buffer_size = p_array.size();
4483
4484
ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
4485
4486
Ref<Image> image = _svg_scalable_mem_loader_func(p_array.ptr(), buffer_size, scale);
4487
ERR_FAIL_COND_V(image.is_null(), ERR_PARSE_ERROR);
4488
4489
copy_internals_from(image);
4490
4491
return OK;
4492
}
4493
4494
Error Image::load_svg_from_string(const String &p_svg_str, float scale) {
4495
return load_svg_from_buffer(p_svg_str.to_utf8_buffer(), scale);
4496
}
4497
4498
Error Image::load_ktx_from_buffer(const Vector<uint8_t> &p_array) {
4499
ERR_FAIL_NULL_V_MSG(
4500
_ktx_mem_loader_func,
4501
ERR_UNAVAILABLE,
4502
"The KTX module isn't enabled. Recompile the Godot editor or export template binary with the `module_ktx_enabled=yes` SCons option.");
4503
return _load_from_buffer(p_array, _ktx_mem_loader_func);
4504
}
4505
4506
void Image::convert_rg_to_ra_rgba8() {
4507
ERR_FAIL_COND(format != FORMAT_RGBA8);
4508
ERR_FAIL_COND(data.is_empty());
4509
4510
int s = data.size();
4511
uint8_t *w = data.ptrw();
4512
for (int i = 0; i < s; i += 4) {
4513
w[i + 3] = w[i + 1];
4514
w[i + 1] = 0;
4515
w[i + 2] = 0;
4516
}
4517
}
4518
4519
void Image::convert_ra_rgba8_to_rg() {
4520
ERR_FAIL_COND(format != FORMAT_RGBA8);
4521
ERR_FAIL_COND(data.is_empty());
4522
4523
int s = data.size();
4524
uint8_t *w = data.ptrw();
4525
for (int i = 0; i < s; i += 4) {
4526
w[i + 1] = w[i + 3];
4527
w[i + 2] = 0;
4528
w[i + 3] = 255;
4529
}
4530
}
4531
4532
void Image::convert_rgba8_to_bgra8() {
4533
ERR_FAIL_COND(format != FORMAT_RGBA8);
4534
ERR_FAIL_COND(data.is_empty());
4535
4536
int s = data.size();
4537
uint8_t *w = data.ptrw();
4538
for (int i = 0; i < s; i += 4) {
4539
uint8_t r = w[i];
4540
w[i] = w[i + 2]; // Swap R to B
4541
w[i + 2] = r; // Swap B to R
4542
}
4543
}
4544
4545
Error Image::_load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader) {
4546
int buffer_size = p_array.size();
4547
4548
ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
4549
ERR_FAIL_NULL_V(p_loader, ERR_INVALID_PARAMETER);
4550
4551
const uint8_t *r = p_array.ptr();
4552
4553
Ref<Image> image = p_loader(r, buffer_size);
4554
ERR_FAIL_COND_V(image.is_null(), ERR_PARSE_ERROR);
4555
4556
copy_internals_from(image);
4557
4558
return OK;
4559
}
4560
4561
void Image::average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d) {
4562
p_out = static_cast<uint8_t>((p_a + p_b + p_c + p_d + 2) >> 2);
4563
}
4564
4565
void Image::average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d) {
4566
p_out = (p_a + p_b + p_c + p_d) * 0.25f;
4567
}
4568
4569
void Image::average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4570
p_out = Math::make_half_float((Math::half_to_float(p_a) + Math::half_to_float(p_b) + Math::half_to_float(p_c) + Math::half_to_float(p_d)) * 0.25f);
4571
}
4572
4573
void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d) {
4574
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
4575
}
4576
4577
void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4578
p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
4579
}
4580
4581
void Image::average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4582
p_out = color_to_rgba4444((color_from_rgba4444(p_a) + color_from_rgba4444(p_b) + color_from_rgba4444(p_c) + color_from_rgba4444(p_d)) * 0.25f);
4583
}
4584
4585
void Image::average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4586
p_out = color_to_rgb565((color_from_rgb565(p_a) + color_from_rgb565(p_b) + color_from_rgb565(p_c) + color_from_rgb565(p_d)) * 0.25f);
4587
}
4588
4589
void Image::renormalize_uint8(uint8_t *p_rgb) {
4590
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
4591
n *= 2.0;
4592
n -= Vector3(1, 1, 1);
4593
n.normalize();
4594
n += Vector3(1, 1, 1);
4595
n *= 0.5;
4596
n *= 255;
4597
p_rgb[0] = CLAMP(int(Math::round(n.x)), 0, 255);
4598
p_rgb[1] = CLAMP(int(Math::round(n.y)), 0, 255);
4599
p_rgb[2] = CLAMP(int(Math::round(n.z)), 0, 255);
4600
}
4601
4602
void Image::renormalize_float(float *p_rgb) {
4603
Vector3 n(p_rgb[0], p_rgb[1], p_rgb[2]);
4604
n *= 2.0;
4605
n -= Vector3(1, 1, 1);
4606
n.normalize();
4607
n += Vector3(1, 1, 1);
4608
n *= 0.5;
4609
p_rgb[0] = n.x;
4610
p_rgb[1] = n.y;
4611
p_rgb[2] = n.z;
4612
}
4613
4614
void Image::renormalize_half(uint16_t *p_rgb) {
4615
Vector3 n(Math::half_to_float(p_rgb[0]), Math::half_to_float(p_rgb[1]), Math::half_to_float(p_rgb[2]));
4616
n *= 2.0;
4617
n -= Vector3(1, 1, 1);
4618
n.normalize();
4619
n += Vector3(1, 1, 1);
4620
n *= 0.5;
4621
p_rgb[0] = Math::make_half_float(n.x);
4622
p_rgb[1] = Math::make_half_float(n.y);
4623
p_rgb[2] = Math::make_half_float(n.z);
4624
}
4625
4626
void Image::renormalize_uint16(uint16_t *p_rgb) {
4627
Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
4628
n *= 2.0;
4629
n -= Vector3(1, 1, 1);
4630
n.normalize();
4631
n += Vector3(1, 1, 1);
4632
n *= 0.5;
4633
n *= 65535;
4634
p_rgb[0] = CLAMP(int(Math::round(n.x)), 0, 65535);
4635
p_rgb[1] = CLAMP(int(Math::round(n.y)), 0, 65535);
4636
p_rgb[2] = CLAMP(int(Math::round(n.z)), 0, 65535);
4637
}
4638
4639
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
4640
width = 0;
4641
height = 0;
4642
mipmaps = false;
4643
format = FORMAT_L8;
4644
4645
if (_png_mem_loader_func) {
4646
copy_internals_from(_png_mem_loader_func(p_mem_png_jpg, p_len));
4647
}
4648
4649
if (is_empty() && _jpg_mem_loader_func) {
4650
copy_internals_from(_jpg_mem_loader_func(p_mem_png_jpg, p_len));
4651
}
4652
4653
if (is_empty() && _webp_mem_loader_func) {
4654
copy_internals_from(_webp_mem_loader_func(p_mem_png_jpg, p_len));
4655
}
4656
}
4657
4658
Ref<Resource> Image::_duplicate(const DuplicateParams &p_params) const {
4659
Ref<Image> copy;
4660
copy.instantiate();
4661
copy->_copy_internals_from(*this);
4662
return copy;
4663
}
4664
4665
void Image::set_as_black() {
4666
memset(data.ptrw(), 0, data.size());
4667
}
4668
4669
void Image::copy_internals_from(const Ref<Image> &p_image) {
4670
ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object.");
4671
format = p_image->format;
4672
width = p_image->width;
4673
height = p_image->height;
4674
mipmaps = p_image->mipmaps;
4675
data = p_image->data;
4676
}
4677
4678
Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric) {
4679
// https://github.com/richgel999/bc7enc_rdo/blob/master/LICENSE
4680
//
4681
// This is free and unencumbered software released into the public domain.
4682
// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
4683
// software, either in source code form or as a compiled binary, for any purpose,
4684
// commercial or non - commercial, and by any means.
4685
// In jurisdictions that recognize copyright laws, the author or authors of this
4686
// software dedicate any and all copyright interest in the software to the public
4687
// domain. We make this dedication for the benefit of the public at large and to
4688
// the detriment of our heirs and successors. We intend this dedication to be an
4689
// overt act of relinquishment in perpetuity of all present and future rights to
4690
// this software under copyright law.
4691
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4692
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4693
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
4694
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
4695
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4696
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4697
4698
Dictionary result;
4699
result["max"] = Math::INF;
4700
result["mean"] = Math::INF;
4701
result["mean_squared"] = Math::INF;
4702
result["root_mean_squared"] = Math::INF;
4703
result["peak_snr"] = 0.0f;
4704
4705
ERR_FAIL_COND_V(p_compared_image.is_null(), result);
4706
Error err = OK;
4707
Ref<Image> compared_image = duplicate(true);
4708
if (compared_image->is_compressed()) {
4709
err = compared_image->decompress();
4710
}
4711
ERR_FAIL_COND_V(err != OK, result);
4712
Ref<Image> source_image = p_compared_image->duplicate(true);
4713
if (source_image->is_compressed()) {
4714
err = source_image->decompress();
4715
}
4716
ERR_FAIL_COND_V(err != OK, result);
4717
4718
ERR_FAIL_COND_V_MSG((compared_image->get_format() >= Image::FORMAT_RH) && (compared_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported.");
4719
ERR_FAIL_COND_V_MSG((source_image->get_format() >= Image::FORMAT_RH) && (source_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported.");
4720
4721
double image_metric_max, image_metric_mean, image_metric_mean_squared, image_metric_root_mean_squared, image_metric_peak_snr = 0.0;
4722
const bool average_component_error = true;
4723
4724
const uint32_t w = MIN(compared_image->get_width(), source_image->get_width());
4725
const uint32_t h = MIN(compared_image->get_height(), source_image->get_height());
4726
4727
// Histogram approach originally due to Charles Bloom.
4728
double hist[256];
4729
memset(hist, 0, sizeof(hist));
4730
4731
for (uint32_t y = 0; y < h; y++) {
4732
for (uint32_t x = 0; x < w; x++) {
4733
const Color color_a = compared_image->get_pixel(x, y);
4734
4735
const Color color_b = source_image->get_pixel(x, y);
4736
4737
if (!p_luma_metric) {
4738
ERR_FAIL_COND_V_MSG(color_a.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
4739
ERR_FAIL_COND_V_MSG(color_b.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
4740
hist[Math::abs(color_a.get_r8() - color_b.get_r8())]++;
4741
ERR_FAIL_COND_V_MSG(color_a.g > 1.0f, Dictionary(), "Can't compare HDR colors.");
4742
ERR_FAIL_COND_V_MSG(color_b.g > 1.0f, Dictionary(), "Can't compare HDR colors.");
4743
hist[Math::abs(color_a.get_g8() - color_b.get_g8())]++;
4744
ERR_FAIL_COND_V_MSG(color_a.b > 1.0f, Dictionary(), "Can't compare HDR colors.");
4745
ERR_FAIL_COND_V_MSG(color_b.b > 1.0f, Dictionary(), "Can't compare HDR colors.");
4746
hist[Math::abs(color_a.get_b8() - color_b.get_b8())]++;
4747
ERR_FAIL_COND_V_MSG(color_a.a > 1.0f, Dictionary(), "Can't compare HDR colors.");
4748
ERR_FAIL_COND_V_MSG(color_b.a > 1.0f, Dictionary(), "Can't compare HDR colors.");
4749
hist[Math::abs(color_a.get_a8() - color_b.get_a8())]++;
4750
} else {
4751
ERR_FAIL_COND_V_MSG(color_a.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
4752
ERR_FAIL_COND_V_MSG(color_b.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
4753
// REC709 weightings
4754
int luma_a = (13938U * color_a.get_r8() + 46869U * color_a.get_g8() + 4729U * color_a.get_b8() + 32768U) >> 16U;
4755
int luma_b = (13938U * color_b.get_r8() + 46869U * color_b.get_g8() + 4729U * color_b.get_b8() + 32768U) >> 16U;
4756
hist[Math::abs(luma_a - luma_b)]++;
4757
}
4758
}
4759
}
4760
4761
image_metric_max = 0;
4762
double sum = 0.0f, sum2 = 0.0f;
4763
for (uint32_t i = 0; i < 256; i++) {
4764
if (!hist[i]) {
4765
continue;
4766
}
4767
4768
image_metric_max = i;
4769
4770
double x = i * hist[i];
4771
4772
sum += x;
4773
sum2 += i * x;
4774
}
4775
4776
// See http://richg42.blogspot.com/2016/09/how-to-compute-psnr-from-old-berkeley.html
4777
double total_values = w * h;
4778
4779
if (average_component_error) {
4780
total_values *= 4;
4781
}
4782
4783
image_metric_mean = CLAMP(sum / total_values, 0.0f, 255.0f);
4784
image_metric_mean_squared = CLAMP(sum2 / total_values, 0.0f, 255.0f * 255.0f);
4785
4786
image_metric_root_mean_squared = std::sqrt(image_metric_mean_squared);
4787
4788
if (!image_metric_root_mean_squared) {
4789
image_metric_peak_snr = 1e+10f;
4790
} else {
4791
image_metric_peak_snr = CLAMP(std::log10(255.0f / image_metric_root_mean_squared) * 20.0f, 0.0f, 500.0f);
4792
}
4793
result["max"] = image_metric_max;
4794
result["mean"] = image_metric_mean;
4795
result["mean_squared"] = image_metric_mean_squared;
4796
result["root_mean_squared"] = image_metric_root_mean_squared;
4797
result["peak_snr"] = image_metric_peak_snr;
4798
return result;
4799
}
4800
4801