2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/imaging/common/loader-ktx.h>
22 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
29 namespace TizenPlatform
33 /** Max width or height of an image. */
34 const unsigned MAX_TEXTURE_DIMENSION = 4096;
35 /** Max bytes of image data allowed. Not a precise number, just a sanity check. */
36 const unsigned MAX_IMAGE_DATA_SIZE = MAX_TEXTURE_DIMENSION * MAX_TEXTURE_DIMENSION;
37 /** We don't read any of this but limit it to a resonable amount in order to be
38 * friendly to files from random tools. */
39 const unsigned MAX_BYTES_OF_KEYVALUE_DATA = 65536U;
43 const Byte FileIdentifier[] = {
44 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
46 /** The formats we support inside a KTX file container.
47 * Currently only compressed formats are allowed as we'd rather
48 * use a PNG or JPEG with their own compression for the general
50 enum KtxInternalFormat
54 // GLES 2 Extension formats:
55 KTX_ETC1_RGB8_OES = 0x8D64,
56 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
58 // GLES 3 Standard compressed formats (values same as in gl3.h):
59 KTX_COMPRESSED_R11_EAC = 0x9270,
60 KTX_COMPRESSED_SIGNED_R11_EAC = 0x9271,
61 KTX_COMPRESSED_RG11_EAC = 0x9272,
62 KTX_COMPRESSED_SIGNED_RG11_EAC = 0x9273,
63 KTX_COMPRESSED_RGB8_ETC2 = 0x9274,
64 KTX_COMPRESSED_SRGB8_ETC2 = 0x9275,
65 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
66 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
67 KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
68 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
70 // GLES 3.1 compressed formats:
71 KTX_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
72 KTX_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1,
73 KTX_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2,
74 KTX_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3,
75 KTX_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4,
76 KTX_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5,
77 KTX_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6,
78 KTX_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7,
79 KTX_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8,
80 KTX_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9,
81 KTX_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA,
82 KTX_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB,
83 KTX_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC,
84 KTX_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD,
85 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
86 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1,
87 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2,
88 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3,
89 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4,
90 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5,
91 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6,
92 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7,
93 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8,
94 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9,
95 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA,
96 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB,
97 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC,
98 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD,
100 // Uncompressed Alpha format
101 KTX_UNCOMPRESSED_ALPHA8 = 0x1906,
106 const unsigned KtxInternalFormats[] =
108 // GLES 2 Extension formats:
110 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
112 // GLES 3 Standard compressed formats:
113 KTX_COMPRESSED_R11_EAC,
114 KTX_COMPRESSED_SIGNED_R11_EAC,
115 KTX_COMPRESSED_RG11_EAC,
116 KTX_COMPRESSED_SIGNED_RG11_EAC,
117 KTX_COMPRESSED_RGB8_ETC2,
118 KTX_COMPRESSED_SRGB8_ETC2,
119 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
120 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
121 KTX_COMPRESSED_RGBA8_ETC2_EAC,
122 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
124 // GLES 3.1 Compressed formats:
125 KTX_COMPRESSED_RGBA_ASTC_4x4_KHR,
126 KTX_COMPRESSED_RGBA_ASTC_5x4_KHR,
127 KTX_COMPRESSED_RGBA_ASTC_5x5_KHR,
128 KTX_COMPRESSED_RGBA_ASTC_6x5_KHR,
129 KTX_COMPRESSED_RGBA_ASTC_6x6_KHR,
130 KTX_COMPRESSED_RGBA_ASTC_8x5_KHR,
131 KTX_COMPRESSED_RGBA_ASTC_8x6_KHR,
132 KTX_COMPRESSED_RGBA_ASTC_8x8_KHR,
133 KTX_COMPRESSED_RGBA_ASTC_10x5_KHR,
134 KTX_COMPRESSED_RGBA_ASTC_10x6_KHR,
135 KTX_COMPRESSED_RGBA_ASTC_10x8_KHR,
136 KTX_COMPRESSED_RGBA_ASTC_10x10_KHR,
137 KTX_COMPRESSED_RGBA_ASTC_12x10_KHR,
138 KTX_COMPRESSED_RGBA_ASTC_12x12_KHR,
139 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
140 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
141 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
142 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
143 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
144 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
145 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
146 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
147 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
148 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
149 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
150 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
151 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
152 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
154 // Uncompressed Alpha format
155 KTX_UNCOMPRESSED_ALPHA8,
166 uint32_t glInternalFormat;
167 uint32_t glBaseInternalFormat;
169 uint32_t pixelHeight;
171 uint32_t numberOfArrayElements;
172 uint32_t numberOfFaces;
173 uint32_t numberOfMipmapLevels;
174 uint32_t bytesOfKeyValueData;
175 } __attribute__((__packed__));
176 // Packed attribute stops the structure from being aligned to compiler defaults
177 // so we can be sure of reading the whole thing from file in one call to fread.
180 * Function to read from the file directly into our structure.
181 * @param[in] fp The file to read from
182 * @param[out] header The structure we want to store our information in
183 * @return true, if read successful, false otherwise
185 inline bool ReadHeader(FILE* filePointer, KtxFileHeader& header)
187 const unsigned int readLength = sizeof(KtxFileHeader);
189 // Load the information directly into our structure
190 if(DALI_UNLIKELY(fread(&header, 1, readLength, filePointer) != readLength))
198 /** Check whether the array passed in is the right size and matches the magic
199 * values defined to be at the start of a KTX file by the specification.*/
200 template<int BYTES_IN_SIGNATURE>
201 bool CheckFileIdentifier(const Byte* const signature)
203 const unsigned signatureSize = BYTES_IN_SIGNATURE;
204 const unsigned identifierSize = sizeof(FileIdentifier);
205 static_assert(signatureSize == identifierSize);
206 const bool signatureGood = 0 == memcmp(signature, FileIdentifier, std::min(signatureSize, identifierSize));
207 return signatureGood;
211 * @returns True if the argument is a GLES compressed texture format that we support.
213 bool ValidInternalFormat(const unsigned format)
215 unsigned candidateFormat = 0;
216 for(unsigned iFormat = 0; (candidateFormat = KtxInternalFormats[iFormat]) != KTX_SENTINEL; ++iFormat)
218 if(format == candidateFormat)
223 DALI_LOG_ERROR("Rejecting unsupported compressed format when loading compressed texture from KTX file: 0x%x.\n", format);
228 * @returns The Pixel::Format Dali enum corresponding to the KTX internal format
229 * passed in, or Pixel::INVALID_PIXEL_FORMAT if the format is not valid.
231 bool ConvertPixelFormat(const uint32_t ktxPixelFormat, Dali::Pixel::Format& format)
233 using namespace Dali::Pixel;
234 switch(ktxPixelFormat)
236 // GLES 2 extension compressed formats:
237 case KTX_ETC1_RGB8_OES:
239 format = COMPRESSED_RGB8_ETC1;
242 case KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
244 format = COMPRESSED_RGB_PVRTC_4BPPV1;
248 // GLES 3 extension compressed formats:
249 case KTX_COMPRESSED_R11_EAC:
251 format = COMPRESSED_R11_EAC;
254 case KTX_COMPRESSED_SIGNED_R11_EAC:
256 format = COMPRESSED_SIGNED_R11_EAC;
259 case KTX_COMPRESSED_RG11_EAC:
261 format = COMPRESSED_RG11_EAC;
264 case KTX_COMPRESSED_SIGNED_RG11_EAC:
266 format = COMPRESSED_SIGNED_RG11_EAC;
269 case KTX_COMPRESSED_RGB8_ETC2:
271 format = COMPRESSED_RGB8_ETC2;
274 case KTX_COMPRESSED_SRGB8_ETC2:
276 format = COMPRESSED_SRGB8_ETC2;
279 case KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
281 format = COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
284 case KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
286 format = COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
289 case KTX_COMPRESSED_RGBA8_ETC2_EAC:
291 format = COMPRESSED_RGBA8_ETC2_EAC;
294 case KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
296 format = COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
300 // GLES 3.1 extension compressed formats:
301 case KTX_COMPRESSED_RGBA_ASTC_4x4_KHR:
303 format = COMPRESSED_RGBA_ASTC_4x4_KHR;
306 case KTX_COMPRESSED_RGBA_ASTC_5x4_KHR:
308 format = COMPRESSED_RGBA_ASTC_5x4_KHR;
311 case KTX_COMPRESSED_RGBA_ASTC_5x5_KHR:
313 format = COMPRESSED_RGBA_ASTC_5x5_KHR;
316 case KTX_COMPRESSED_RGBA_ASTC_6x5_KHR:
318 format = COMPRESSED_RGBA_ASTC_6x5_KHR;
321 case KTX_COMPRESSED_RGBA_ASTC_6x6_KHR:
323 format = COMPRESSED_RGBA_ASTC_6x6_KHR;
326 case KTX_COMPRESSED_RGBA_ASTC_8x5_KHR:
328 format = COMPRESSED_RGBA_ASTC_8x5_KHR;
331 case KTX_COMPRESSED_RGBA_ASTC_8x6_KHR:
333 format = COMPRESSED_RGBA_ASTC_8x6_KHR;
336 case KTX_COMPRESSED_RGBA_ASTC_8x8_KHR:
338 format = COMPRESSED_RGBA_ASTC_8x8_KHR;
341 case KTX_COMPRESSED_RGBA_ASTC_10x5_KHR:
343 format = COMPRESSED_RGBA_ASTC_10x5_KHR;
346 case KTX_COMPRESSED_RGBA_ASTC_10x6_KHR:
348 format = COMPRESSED_RGBA_ASTC_10x6_KHR;
351 case KTX_COMPRESSED_RGBA_ASTC_10x8_KHR:
353 format = COMPRESSED_RGBA_ASTC_10x8_KHR;
356 case KTX_COMPRESSED_RGBA_ASTC_10x10_KHR:
358 format = COMPRESSED_RGBA_ASTC_10x10_KHR;
361 case KTX_COMPRESSED_RGBA_ASTC_12x10_KHR:
363 format = COMPRESSED_RGBA_ASTC_12x10_KHR;
366 case KTX_COMPRESSED_RGBA_ASTC_12x12_KHR:
368 format = COMPRESSED_RGBA_ASTC_12x12_KHR;
371 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
373 format = COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
376 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
378 format = COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
381 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
383 format = COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
386 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
388 format = COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
391 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
393 format = COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
396 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
398 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
401 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
403 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
406 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
408 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
411 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
413 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
416 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
418 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
421 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
423 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
426 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
428 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
431 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
433 format = COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
436 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
438 format = COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
442 // Uncompressed Alpha format
443 case KTX_UNCOMPRESSED_ALPHA8:
457 bool LoadKtxHeader(FILE* const fp, unsigned int& width, unsigned int& height, KtxFileHeader& fileHeader)
459 // Pull the bytes of the file header in as a block:
460 if(DALI_UNLIKELY(!ReadHeader(fp, fileHeader)))
464 width = fileHeader.pixelWidth;
465 height = fileHeader.pixelHeight;
467 if(DALI_UNLIKELY(width > MAX_TEXTURE_DIMENSION || height > MAX_TEXTURE_DIMENSION))
472 // Validate file header contents meet our minimal subset:
473 const bool signatureGood = CheckFileIdentifier<sizeof(fileHeader.identifier)>(fileHeader.identifier);
474 const bool fileEndiannessMatchesSystemEndianness = fileHeader.endianness == 0x04030201; // Magic number from KTX spec.
475 const bool glTypeIsCompressed = fileHeader.glType == 0;
476 const bool glTypeSizeCompatibleWithCompressedTex = fileHeader.glTypeSize == 1;
477 const bool glFormatCompatibleWithCompressedTex = fileHeader.glFormat == 0;
478 const bool glInternalFormatIsSupportedCompressedTex = ValidInternalFormat(fileHeader.glInternalFormat);
479 // Ignore glBaseInternalFormat
480 const bool textureIsNot3D = fileHeader.pixelDepth == 0 || fileHeader.pixelDepth == 1;
481 const bool textureIsNotAnArray = fileHeader.numberOfArrayElements == 0 || fileHeader.numberOfArrayElements == 1;
482 const bool textureIsNotACubemap = fileHeader.numberOfFaces == 0 || fileHeader.numberOfFaces == 1;
483 const bool textureHasNoMipmapLevels = fileHeader.numberOfMipmapLevels == 0 || fileHeader.numberOfMipmapLevels == 1;
484 const bool keyValueDataNotTooLarge = fileHeader.bytesOfKeyValueData <= MAX_BYTES_OF_KEYVALUE_DATA;
486 bool headerIsValid = signatureGood && fileEndiannessMatchesSystemEndianness &&
487 glTypeSizeCompatibleWithCompressedTex && textureIsNot3D && textureIsNotAnArray &&
488 textureIsNotACubemap && textureHasNoMipmapLevels && keyValueDataNotTooLarge;
490 if(!glTypeIsCompressed) // check for uncompressed Alpha
492 const bool isAlpha = ((fileHeader.glBaseInternalFormat == KTX_UNCOMPRESSED_ALPHA8) && (fileHeader.glFormat == KTX_UNCOMPRESSED_ALPHA8) &&
493 (fileHeader.glInternalFormat == KTX_UNCOMPRESSED_ALPHA8));
494 headerIsValid = headerIsValid && isAlpha;
498 headerIsValid = headerIsValid && glFormatCompatibleWithCompressedTex && glInternalFormatIsSupportedCompressedTex;
503 DALI_LOG_ERROR("KTX file invalid or using unsupported features. Header tests: sig: %d, endian: %d, gl_type: %d, gl_type_size: %d, gl_format: %d, internal_format: %d, depth: %d, array: %d, faces: %d, mipmap: %d, vey-vals: %d.\n", 0 + signatureGood, 0 + fileEndiannessMatchesSystemEndianness, 0 + glTypeIsCompressed, 0 + glTypeSizeCompatibleWithCompressedTex, 0 + glFormatCompatibleWithCompressedTex, 0 + glInternalFormatIsSupportedCompressedTex, 0 + textureIsNot3D, 0 + textureIsNotAnArray, 0 + textureIsNotACubemap, 0 + textureHasNoMipmapLevels, 0 + keyValueDataNotTooLarge);
506 // Warn if there is space wasted in the file:
507 if(fileHeader.bytesOfKeyValueData > 0U)
509 DALI_LOG_WARNING("Loading of KTX file with key/value header data requested. This should be stripped in application asset/resource build.\n");
512 return headerIsValid;
515 } // unnamed namespace
517 // File loading API entry-point:
518 bool LoadKtxHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
520 KtxFileHeader fileHeader;
521 FILE* const fp = input.file;
523 bool ret = LoadKtxHeader(fp, width, height, fileHeader);
527 // File loading API entry-point:
528 bool LoadBitmapFromKtx(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
530 static_assert(sizeof(Byte) == 1);
531 static_assert(sizeof(uint32_t) == 4);
533 FILE* const fp = input.file;
534 if(DALI_UNLIKELY(fp == NULL))
536 DALI_LOG_ERROR("Null file handle passed to KTX compressed bitmap file loader.\n");
539 KtxFileHeader fileHeader;
541 // Load the header info
542 unsigned int width, height;
544 if(DALI_UNLIKELY(!LoadKtxHeader(fp, width, height, fileHeader)))
549 // Skip the key-values:
550 const long int imageSizeOffset = sizeof(KtxFileHeader) + fileHeader.bytesOfKeyValueData;
551 if(DALI_UNLIKELY(fseek(fp, imageSizeOffset, SEEK_SET)))
553 DALI_LOG_ERROR("Seek past key/vals in KTX compressed bitmap file failed.\n");
557 // Load the size of the image data:
558 uint32_t imageByteCount = 0;
559 if(DALI_UNLIKELY(fread(&imageByteCount, 1, 4, fp) != 4))
561 DALI_LOG_ERROR("Read of image size failed.\n");
564 // Sanity-check the image size:
565 if(DALI_UNLIKELY(imageByteCount > MAX_IMAGE_DATA_SIZE ||
566 // A compressed texture should certainly be less than 2 bytes per texel:
567 imageByteCount > width * height * 2))
569 DALI_LOG_ERROR("KTX file with too-large image-data field.\n");
573 Pixel::Format pixelFormat;
574 const bool pixelFormatKnown = ConvertPixelFormat(fileHeader.glInternalFormat, pixelFormat);
575 if(DALI_UNLIKELY(!pixelFormatKnown))
577 DALI_LOG_ERROR("No internal pixel format supported for KTX file pixel format.\n");
581 // Load up the image bytes:
582 bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
584 // Compressed format won't allocate the buffer
585 auto pixels = bitmap.GetBuffer();
588 // allocate buffer manually
589 auto& impl = GetImplementation(bitmap);
590 impl.AllocateFixedSize(imageByteCount);
591 pixels = bitmap.GetBuffer();
594 if(DALI_UNLIKELY(!pixels))
596 DALI_LOG_ERROR("Unable to reserve a pixel buffer to load the requested bitmap into.\n");
600 const size_t bytesRead = fread(pixels, 1, imageByteCount, fp);
601 if(DALI_UNLIKELY(bytesRead != imageByteCount))
603 DALI_LOG_ERROR("Read of image pixel data failed.\n");
610 } // namespace TizenPlatform