2525#include < jxl/decode_cxx.h>
2626#include < jxl/resizable_parallel_runner_cxx.h>
2727
28- // =======
29- // Classes
30- // =======
31-
32- // Generic client data structure, used by JPEG and PNG
33- struct clientData_s {
34- IConsole* con;
35- const char * fileName;
36- ioStream_c* io;
37- };
28+ #include < gli/gli.hpp>
3829
3930// =========
4031// Raw Image
4132// =========
4233
4334image_c::image_c (IConsole* conHnd)
4435 : con(conHnd)
45- {
46- dat = NULL ;
47- }
48-
49- image_c::~image_c ()
50- {
51- Free ();
52- }
36+ {}
5337
5438void image_c::CopyRaw (int inType, dword inWidth, dword inHeight, const byte* inDat)
5539{
56- if (dat) delete[] dat;
57- dat = nullptr ;
40+ // Populate legacy fields
5841 comp = inType & 0xF ;
5942 type = inType;
6043 width = inWidth;
6144 height = inHeight;
62- dat = new byte[width * height * comp];
63- memcpy (dat, inDat, width * height * comp);
45+
46+ // Populate gli texture
47+ PopulateTex (inDat);
6448}
6549
6650void image_c::Free ()
6751{
68- delete[] dat;
69- dat = NULL ;
52+ tex = {};
53+ }
54+
55+ // TODO(zao): Make this function only care about unpacked source data.
56+ void image_c::PopulateTex (const byte* dat)
57+ {
58+ gli::format format = gli::format::FORMAT_UNDEFINED ;
59+ const glm::ivec2 extent{ width, height };
60+ size_t dataSize = width * height * comp; // Common default for regular formats.
61+
62+ const auto PhysicalSize = [](dword width, dword height, dword blockSize, dword side = 4 ) -> dword {
63+ dword numBlocks = ((width + side - 1 ) / side) * ((height + side - 1 ) / side);
64+ return numBlocks * blockSize;
65+ };
66+ switch ((imageType_s)type) {
67+ case imageType_s::IMGTYPE_NONE :
68+ tex = {};
69+ return ;
70+ case imageType_s::IMGTYPE_GRAY :
71+ format = gli::format::FORMAT_R8_SRGB_PACK8 ;
72+ break ;
73+ case imageType_s::IMGTYPE_RGB :
74+ format = gli::format::FORMAT_RGB8_SRGB_PACK8 ;
75+ break ;
76+ case imageType_s::IMGTYPE_RGBA :
77+ format = gli::format::FORMAT_RGBA8_SNORM_PACK8 ;
78+ break ;
79+ case imageType_s::IMGTYPE_RGBA_BC1 :
80+ format = gli::format::FORMAT_RGBA_DXT1_SRGB_BLOCK8 ;
81+ dataSize = PhysicalSize (width, height, 8 );
82+ break ;
83+ case imageType_s::IMGTYPE_RGBA_BC2 :
84+ format = gli::format::FORMAT_RGBA_DXT3_SRGB_BLOCK16 ;
85+ dataSize = PhysicalSize (width, height, 16 );
86+ break ;
87+ case imageType_s::IMGTYPE_RGBA_BC3 :
88+ format = gli::format::FORMAT_RGBA_DXT5_SRGB_BLOCK16 ;
89+ dataSize = PhysicalSize (width, height, 16 );
90+ break ;
91+ case imageType_s::IMGTYPE_RGBA_BC7 :
92+ format = gli::format::FORMAT_RGBA_BP_SRGB_BLOCK16 ;
93+ dataSize = PhysicalSize (width, height, 16 );
94+ }
95+
96+ tex = gli::texture2d (format, extent, 1 );
97+ if (tex.size (0 ) == dataSize)
98+ memcpy (tex.data (0 , 0 , 0 ), dat, dataSize);
99+ else
100+ assert (tex.size (0 ) == dataSize);
70101}
71102
72103bool image_c::Load (const char * fileName, std::optional<size_callback_t > sizeCallback)
@@ -176,7 +207,8 @@ bool targa_c::Load(const char* fileName, std::optional<size_callback_t> sizeCall
176207 comp = hdr.depth >> 3 ;
177208 type = ittable[it_m][2 ];
178209 int rowSize = width * comp;
179- dat = new byte[height * rowSize];
210+ std::vector<byte> datBuf (height * rowSize);
211+ byte* dat = datBuf.data ();
180212 bool flipV = !(hdr.descriptor & 0x20 );
181213 if (hdr.imgType & 8 ) {
182214 // Decode RLE image
@@ -221,6 +253,8 @@ bool targa_c::Load(const char* fileName, std::optional<size_callback_t> sizeCall
221253 }
222254 }
223255
256+ PopulateTex (dat);
257+
224258 return false ;
225259}
226260
@@ -236,10 +270,13 @@ bool targa_c::Save(const char* fileName)
236270 return true ;
237271 }
238272
273+ if (is_compressed (tex.format ()))
274+ return true ;
275+
239276 auto rc = stbi_write_tga_to_func ([](void * ctx, void * data, int size) {
240277 auto out = (fileOutputStream_c*)ctx;
241278 out->Write (data, size);
242- }, &out, width, height, comp, dat );
279+ }, &out, width, height, comp, tex. data ( 0 , 0 , 0 ) );
243280
244281 return !rc;
245282}
@@ -282,10 +319,10 @@ bool jpeg_c::Load(const char* fileName, std::optional<size_callback_t> sizeCallb
282319 height = y;
283320 comp = in_comp;
284321 type = in_comp == 1 ? IMGTYPE_GRAY : IMGTYPE_RGB ;
285- const size_t byteSize = width * height * comp;
286- dat = new byte[byteSize];
287- std::copy_n (data, byteSize, dat);
322+
323+ PopulateTex (data);
288324 stbi_image_free (data);
325+
289326 return false ;
290327}
291328
@@ -302,10 +339,13 @@ bool jpeg_c::Save(const char* fileName)
302339 return true ;
303340 }
304341
342+ if (is_compressed (tex.format ()))
343+ return true ;
344+
305345 int rc = stbi_write_jpg_to_func ([](void * ctx, void * data, int size) {
306346 auto out = (fileOutputStream_c*)ctx;
307347 out->Write (data, size);
308- }, &out, width, height, comp, dat , quality);
348+ }, &out, width, height, comp, tex. data ( 0 , 0 , 0 ) , quality);
309349 return !rc;
310350}
311351
@@ -344,10 +384,10 @@ bool png_c::Load(const char* fileName, std::optional<size_callback_t> sizeCallba
344384 stbi_image_free (data);
345385 return true ;
346386 }
347- const size_t byteSize = width * height * comp;
348- dat = new byte[byteSize];
349- std::copy_n (data, byteSize, dat);
387+
388+ PopulateTex (data);
350389 stbi_image_free (data);
390+
351391 return false ;
352392}
353393
@@ -366,7 +406,7 @@ bool png_c::Save(const char* fileName)
366406 auto rc = stbi_write_png_to_func ([](void * ctx, void * data, int size) {
367407 auto out = (fileOutputStream_c*)ctx;
368408 out->Write (data, size);
369- }, &out, width, height, comp, dat , width * comp);
409+ }, &out, width, height, comp, tex. data ( 0 , 0 , 0 ) , width * comp);
370410
371411 return !rc;
372412}
@@ -401,10 +441,10 @@ bool gif_c::Load(const char* fileName, std::optional<size_callback_t> sizeCallba
401441
402442 comp = in_comp;
403443 type = IMGTYPE_RGBA ;
404- const size_t byteSize = width * height * comp;
405- dat = new byte[byteSize];
406- std::copy_n (data, byteSize, dat);
444+
445+ PopulateTex (data);
407446 stbi_image_free (data);
447+
408448 return false ;
409449 }
410450}
@@ -449,6 +489,8 @@ bool jpeg_xl_c::Load(const char* fileName, std::optional<size_callback_t> sizeCa
449489 JxlDecoderSetInput (dec.get (), fileData.data (), fileData.size ());
450490 JxlDecoderCloseInput (dec.get ());
451491
492+ std::vector<byte> datBuf;
493+
452494 while (true ) {
453495 JxlDecoderStatus status = JxlDecoderProcessInput (dec.get ());
454496
@@ -484,18 +526,19 @@ bool jpeg_xl_c::Load(const char* fileName, std::optional<size_callback_t> sizeCa
484526 size_t bufferSize{};
485527 if (JXL_DEC_SUCCESS != JxlDecoderImageOutBufferSize (dec.get (), &format, &bufferSize))
486528 return true ;
487- dat = new byte[width * height * comp];
488- if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer (dec.get (), &format, dat, bufferSize))
529+ assert (bufferSize == width * height * comp);
530+ datBuf.resize (bufferSize);
531+ if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer (dec.get (), &format, datBuf.data (), bufferSize))
489532 return true ;
490533 } break ;
491534
535+ case JXL_DEC_SUCCESS :
492536 case JXL_DEC_FULL_IMAGE : {
493537 // We don't care about animations, consider loading completed when a full image has obtained.
538+ PopulateTex (datBuf.data ());
494539 return false ;
495540 } break ;
496541
497- case JXL_DEC_SUCCESS :
498- return false ;
499542 default :
500543 continue ;
501544 }
0 commit comments