2 * Copyright (c) 2017 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>
23 #include <dali/public-api/common/compile-time-assert.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
26 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
28 #include <dali/internal/system/common/file-closer.h>
30 using namespace Dali::Internal::Platform;
35 namespace TizenPlatform
41 /** Max width or height of an image. */
42 const unsigned MAX_TEXTURE_DIMENSION = 4096;
43 /** Max bytes of image data allowed. Not a precise number, just a sanity check. */
44 const unsigned MAX_IMAGE_DATA_SIZE = MAX_TEXTURE_DIMENSION * MAX_TEXTURE_DIMENSION;
45 /** We don't read any of this but limit it to a resonable amount in order to be
46 * friendly to files from random tools. */
47 const unsigned MAX_BYTES_OF_KEYVALUE_DATA = 65536U;
51 const Byte FileIdentifier[] = {
52 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
56 /** The formats we support inside a KTX file container.
57 * Currently only compressed formats are allowed as we'd rather
58 * use a PNG or JPEG with their own compression for the general
60 enum KtxInternalFormat
64 // GLES 2 Extension formats:
65 KTX_ETC1_RGB8_OES = 0x8D64,
66 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
68 // GLES 3 Standard compressed formats (values same as in gl3.h):
69 KTX_COMPRESSED_R11_EAC = 0x9270,
70 KTX_COMPRESSED_SIGNED_R11_EAC = 0x9271,
71 KTX_COMPRESSED_RG11_EAC = 0x9272,
72 KTX_COMPRESSED_SIGNED_RG11_EAC = 0x9273,
73 KTX_COMPRESSED_RGB8_ETC2 = 0x9274,
74 KTX_COMPRESSED_SRGB8_ETC2 = 0x9275,
75 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
76 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
77 KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
78 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
80 // GLES 3.1 compressed formats:
81 KTX_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
82 KTX_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1,
83 KTX_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2,
84 KTX_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3,
85 KTX_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4,
86 KTX_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5,
87 KTX_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6,
88 KTX_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7,
89 KTX_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8,
90 KTX_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9,
91 KTX_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA,
92 KTX_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB,
93 KTX_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC,
94 KTX_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD,
95 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
96 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1,
97 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2,
98 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3,
99 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4,
100 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5,
101 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6,
102 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7,
103 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8,
104 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9,
105 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA,
106 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB,
107 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC,
108 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD,
110 // Uncompressed Alpha format
111 KTX_UNCOMPRESSED_ALPHA8 = 0x1906,
116 const unsigned KtxInternalFormats[] =
118 // GLES 2 Extension formats:
120 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
122 // GLES 3 Standard compressed formats:
123 KTX_COMPRESSED_R11_EAC,
124 KTX_COMPRESSED_SIGNED_R11_EAC,
125 KTX_COMPRESSED_RG11_EAC,
126 KTX_COMPRESSED_SIGNED_RG11_EAC,
127 KTX_COMPRESSED_RGB8_ETC2,
128 KTX_COMPRESSED_SRGB8_ETC2,
129 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
130 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
131 KTX_COMPRESSED_RGBA8_ETC2_EAC,
132 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
134 // GLES 3.1 Compressed formats:
135 KTX_COMPRESSED_RGBA_ASTC_4x4_KHR,
136 KTX_COMPRESSED_RGBA_ASTC_5x4_KHR,
137 KTX_COMPRESSED_RGBA_ASTC_5x5_KHR,
138 KTX_COMPRESSED_RGBA_ASTC_6x5_KHR,
139 KTX_COMPRESSED_RGBA_ASTC_6x6_KHR,
140 KTX_COMPRESSED_RGBA_ASTC_8x5_KHR,
141 KTX_COMPRESSED_RGBA_ASTC_8x6_KHR,
142 KTX_COMPRESSED_RGBA_ASTC_8x8_KHR,
143 KTX_COMPRESSED_RGBA_ASTC_10x5_KHR,
144 KTX_COMPRESSED_RGBA_ASTC_10x6_KHR,
145 KTX_COMPRESSED_RGBA_ASTC_10x8_KHR,
146 KTX_COMPRESSED_RGBA_ASTC_10x10_KHR,
147 KTX_COMPRESSED_RGBA_ASTC_12x10_KHR,
148 KTX_COMPRESSED_RGBA_ASTC_12x12_KHR,
149 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
150 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
151 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
152 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
153 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
154 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
155 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
156 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
157 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
158 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
159 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
160 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
161 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
162 KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
164 // Uncompressed Alpha format
165 KTX_UNCOMPRESSED_ALPHA8,
177 uint32_t glInternalFormat;
178 uint32_t glBaseInternalFormat;
180 uint32_t pixelHeight;
182 uint32_t numberOfArrayElements;
183 uint32_t numberOfFaces;
184 uint32_t numberOfMipmapLevels;
185 uint32_t bytesOfKeyValueData;
186 } __attribute__ ( (__packed__));
187 // Packed attribute stops the structure from being aligned to compiler defaults
188 // so we can be sure of reading the whole thing from file in one call to fread.
191 * Function to read from the file directly into our structure.
192 * @param[in] fp The file to read from
193 * @param[out] header The structure we want to store our information in
194 * @return true, if read successful, false otherwise
196 inline bool ReadHeader( FILE* filePointer, KtxFileHeader& header )
198 const unsigned int readLength = sizeof( KtxFileHeader );
200 // Load the information directly into our structure
201 if( InternalFile::fread( &header, 1, readLength, filePointer ) != readLength )
209 /** Check whether the array passed in is the right size and matches the magic
210 * values defined to be at the start of a KTX file by the specification.*/
211 template<int BYTES_IN_SIGNATURE>
212 bool CheckFileIdentifier(const Byte * const signature)
214 const unsigned signatureSize = BYTES_IN_SIGNATURE;
215 const unsigned identifierSize = sizeof(FileIdentifier);
216 DALI_COMPILE_TIME_ASSERT(signatureSize == identifierSize);
217 const bool signatureGood = 0 == memcmp( signature, FileIdentifier, std::min( signatureSize, identifierSize ) );
218 return signatureGood;
222 * @returns True if the argument is a GLES compressed texture format that we support.
224 bool ValidInternalFormat(const unsigned format)
226 unsigned candidateFormat = 0;
227 for(unsigned iFormat = 0; (candidateFormat = KtxInternalFormats[iFormat]) != KTX_SENTINEL; ++iFormat)
229 if(format == candidateFormat)
234 DALI_LOG_ERROR("Rejecting unsupported compressed format when loading compressed texture from KTX file: 0x%x.\n", format);
239 * @returns The Pixel::Format Dali enum corresponding to the KTX internal format
240 * passed in, or Pixel::INVALID_PIXEL_FORMAT if the format is not valid.
242 bool ConvertPixelFormat(const uint32_t ktxPixelFormat, Dali::Pixel::Format& format)
244 using namespace Dali::Pixel;
245 switch(ktxPixelFormat)
247 // GLES 2 extension compressed formats:
248 case KTX_ETC1_RGB8_OES:
250 format = COMPRESSED_RGB8_ETC1;
253 case KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
255 format = COMPRESSED_RGB_PVRTC_4BPPV1;
259 // GLES 3 extension compressed formats:
260 case KTX_COMPRESSED_R11_EAC:
262 format = COMPRESSED_R11_EAC;
265 case KTX_COMPRESSED_SIGNED_R11_EAC:
267 format = COMPRESSED_SIGNED_R11_EAC;
270 case KTX_COMPRESSED_RG11_EAC:
272 format = COMPRESSED_RG11_EAC;
275 case KTX_COMPRESSED_SIGNED_RG11_EAC:
277 format = COMPRESSED_SIGNED_RG11_EAC;
280 case KTX_COMPRESSED_RGB8_ETC2:
282 format = COMPRESSED_RGB8_ETC2;
285 case KTX_COMPRESSED_SRGB8_ETC2:
287 format = COMPRESSED_SRGB8_ETC2;
290 case KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
292 format = COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
295 case KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
297 format = COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
300 case KTX_COMPRESSED_RGBA8_ETC2_EAC:
302 format = COMPRESSED_RGBA8_ETC2_EAC;
305 case KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
307 format = COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
311 // GLES 3.1 extension compressed formats:
312 case KTX_COMPRESSED_RGBA_ASTC_4x4_KHR:
314 format = COMPRESSED_RGBA_ASTC_4x4_KHR;
317 case KTX_COMPRESSED_RGBA_ASTC_5x4_KHR:
319 format = COMPRESSED_RGBA_ASTC_5x4_KHR;
322 case KTX_COMPRESSED_RGBA_ASTC_5x5_KHR:
324 format = COMPRESSED_RGBA_ASTC_5x5_KHR;
327 case KTX_COMPRESSED_RGBA_ASTC_6x5_KHR:
329 format = COMPRESSED_RGBA_ASTC_6x5_KHR;
332 case KTX_COMPRESSED_RGBA_ASTC_6x6_KHR:
334 format = COMPRESSED_RGBA_ASTC_6x6_KHR;
337 case KTX_COMPRESSED_RGBA_ASTC_8x5_KHR:
339 format = COMPRESSED_RGBA_ASTC_8x5_KHR;
342 case KTX_COMPRESSED_RGBA_ASTC_8x6_KHR:
344 format = COMPRESSED_RGBA_ASTC_8x6_KHR;
347 case KTX_COMPRESSED_RGBA_ASTC_8x8_KHR:
349 format = COMPRESSED_RGBA_ASTC_8x8_KHR;
352 case KTX_COMPRESSED_RGBA_ASTC_10x5_KHR:
354 format = COMPRESSED_RGBA_ASTC_10x5_KHR;
357 case KTX_COMPRESSED_RGBA_ASTC_10x6_KHR:
359 format = COMPRESSED_RGBA_ASTC_10x6_KHR;
362 case KTX_COMPRESSED_RGBA_ASTC_10x8_KHR:
364 format = COMPRESSED_RGBA_ASTC_10x8_KHR;
367 case KTX_COMPRESSED_RGBA_ASTC_10x10_KHR:
369 format = COMPRESSED_RGBA_ASTC_10x10_KHR;
372 case KTX_COMPRESSED_RGBA_ASTC_12x10_KHR:
374 format = COMPRESSED_RGBA_ASTC_12x10_KHR;
377 case KTX_COMPRESSED_RGBA_ASTC_12x12_KHR:
379 format = COMPRESSED_RGBA_ASTC_12x12_KHR;
382 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
384 format = COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
387 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
389 format = COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
392 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
394 format = COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
397 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
399 format = COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
402 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
404 format = COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
407 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
409 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
412 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
414 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
417 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
419 format = COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
422 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
424 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
427 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
429 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
432 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
434 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
437 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
439 format = COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
442 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
444 format = COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
447 case KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
449 format = COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
453 // Uncompressed Alpha format
454 case KTX_UNCOMPRESSED_ALPHA8:
468 bool LoadKtxHeader( FILE * const fp, unsigned int& width, unsigned int& height, KtxFileHeader& fileHeader )
470 // Pull the bytes of the file header in as a block:
471 if ( !ReadHeader( fp, fileHeader ) )
475 width = fileHeader.pixelWidth;
476 height = fileHeader.pixelHeight;
478 if ( width > MAX_TEXTURE_DIMENSION || height > MAX_TEXTURE_DIMENSION )
483 // Validate file header contents meet our minimal subset:
484 const bool signatureGood = CheckFileIdentifier<sizeof(fileHeader.identifier)>(fileHeader.identifier);
485 const bool fileEndiannessMatchesSystemEndianness = fileHeader.endianness == 0x04030201; // Magic number from KTX spec.
486 const bool glTypeIsCompressed = fileHeader.glType == 0;
487 const bool glTypeSizeCompatibleWithCompressedTex = fileHeader.glTypeSize == 1;
488 const bool glFormatCompatibleWithCompressedTex = fileHeader.glFormat == 0;
489 const bool glInternalFormatIsSupportedCompressedTex = ValidInternalFormat(fileHeader.glInternalFormat);
490 // Ignore glBaseInternalFormat
491 const bool textureIsNot3D = fileHeader.pixelDepth == 0 || fileHeader.pixelDepth == 1;
492 const bool textureIsNotAnArray = fileHeader.numberOfArrayElements == 0 || fileHeader.numberOfArrayElements == 1;
493 const bool textureIsNotACubemap = fileHeader.numberOfFaces == 0 || fileHeader.numberOfFaces == 1;
494 const bool textureHasNoMipmapLevels = fileHeader.numberOfMipmapLevels == 0 || fileHeader.numberOfMipmapLevels == 1;
495 const bool keyValueDataNotTooLarge = fileHeader.bytesOfKeyValueData <= MAX_BYTES_OF_KEYVALUE_DATA;
497 bool headerIsValid = signatureGood && fileEndiannessMatchesSystemEndianness &&
498 glTypeSizeCompatibleWithCompressedTex && textureIsNot3D && textureIsNotAnArray &&
499 textureIsNotACubemap && textureHasNoMipmapLevels && keyValueDataNotTooLarge;
501 if( !glTypeIsCompressed ) // check for uncompressed Alpha
503 const bool isAlpha = ( ( fileHeader.glBaseInternalFormat == KTX_UNCOMPRESSED_ALPHA8 ) && ( fileHeader.glFormat == KTX_UNCOMPRESSED_ALPHA8 ) &&
504 ( fileHeader.glInternalFormat == KTX_UNCOMPRESSED_ALPHA8 ) );
505 headerIsValid = headerIsValid && isAlpha;
509 headerIsValid = headerIsValid && glFormatCompatibleWithCompressedTex && glInternalFormatIsSupportedCompressedTex;
514 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);
517 // Warn if there is space wasted in the file:
518 if( fileHeader.bytesOfKeyValueData > 0U )
520 DALI_LOG_WARNING("Loading of KTX file with key/value header data requested. This should be stripped in application asset/resource build.\n");
523 return headerIsValid;
527 } // unnamed namespace
529 // File loading API entry-point:
530 bool LoadKtxHeader( const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height )
532 KtxFileHeader fileHeader;
533 FILE* const fp = input.file;
535 bool ret = LoadKtxHeader(fp, width, height, fileHeader);
539 // File loading API entry-point:
540 bool LoadBitmapFromKtx( const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap )
542 DALI_COMPILE_TIME_ASSERT( sizeof(Byte) == 1);
543 DALI_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4);
545 FILE* const fp = input.file;
548 DALI_LOG_ERROR( "Null file handle passed to KTX compressed bitmap file loader.\n" );
551 KtxFileHeader fileHeader;
553 // Load the header info
554 unsigned int width, height;
556 if (!LoadKtxHeader(fp, width, height, fileHeader))
561 // Skip the key-values:
562 const long int imageSizeOffset = sizeof(KtxFileHeader) + fileHeader.bytesOfKeyValueData;
563 if(InternalFile::fseek(fp, imageSizeOffset, SEEK_SET))
565 DALI_LOG_ERROR( "Seek past key/vals in KTX compressed bitmap file failed.\n" );
569 // Load the size of the image data:
570 uint32_t imageByteCount = 0;
571 if ( InternalFile::fread( &imageByteCount, 1, 4, fp ) != 4 )
573 DALI_LOG_ERROR( "Read of image size failed.\n" );
576 // Sanity-check the image size:
577 if( imageByteCount > MAX_IMAGE_DATA_SIZE ||
578 // A compressed texture should certainly be less than 2 bytes per texel:
579 imageByteCount > width * height * 2)
581 DALI_LOG_ERROR( "KTX file with too-large image-data field.\n" );
585 Pixel::Format pixelFormat;
586 const bool pixelFormatKnown = ConvertPixelFormat(fileHeader.glInternalFormat, pixelFormat);
587 if(!pixelFormatKnown)
589 DALI_LOG_ERROR( "No internal pixel format supported for KTX file pixel format.\n" );
593 // Load up the image bytes:
594 bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
596 // Compressed format won't allocate the buffer
597 auto pixels = bitmap.GetBuffer();
600 // allocate buffer manually
601 auto &impl = GetImplementation(bitmap);
602 impl.AllocateFixedSize(imageByteCount);
603 pixels = bitmap.GetBuffer();
608 DALI_LOG_ERROR( "Unable to reserve a pixel buffer to load the requested bitmap into.\n" );
612 const size_t bytesRead = InternalFile::fread(pixels, 1, imageByteCount, fp);
613 if(bytesRead != imageByteCount)
615 DALI_LOG_ERROR( "Read of image pixel data failed.\n" );
622 } // namespace TizenPlatform