KDbool Image::initWithImageData ( const KDubyte* pData, KDint32 nDataLen ) { KDbool bRet = false; do { CC_BREAK_IF ( !pData || nDataLen <= 0 ); KDubyte* pUnpackedData = nullptr; KDint nUnpackedLen = 0; // detecgt and unzip the compress file if ( ZipUtils::isCCZBuffer ( pData, nDataLen ) ) { nUnpackedLen = ZipUtils::inflateCCZBuffer ( pData, nDataLen, &pUnpackedData ); } else if ( ZipUtils::isGZipBuffer ( pData, nDataLen ) ) { nUnpackedLen = ZipUtils::inflateMemory ( const_cast<KDubyte*> ( pData ), nDataLen, &pUnpackedData ); } else { pUnpackedData = const_cast<KDubyte*> ( pData ); nUnpackedLen = nDataLen; } KDFile* pFile = kdFmemopen ( pUnpackedData, nUnpackedLen, "rb" ); KDoff uOffset = kdFtell ( pFile ); KDImageATX pImage = KD_NULL; do { Texture2D::PixelFormat eFormat = Texture2D::getDefaultAlphaPixelFormat ( ); if ( eFormat == Texture2D::PixelFormat::AUTO ) { pImage = kdGetImageInfoFromStreamATX ( pFile ); CC_BREAK_IF ( !pImage ); KDint nFormat = kdGetImageIntATX ( pImage, KD_IMAGE_FORMAT_ATX ); KDint nBpp = kdGetImageIntATX ( pImage, KD_IMAGE_BITSPERPIXEL_ATX ); KDint nAlpha = kdGetImageIntATX ( pImage, KD_IMAGE_ALPHA_ATX ); KDint nType = kdGetImageIntATX ( pImage, KD_IMAGE_TYPE ); m_eFileType = (Format) nType; kdFreeImageATX ( pImage ); kdFseek ( pFile, uOffset, KD_SEEK_SET ); switch ( nFormat ) { case KD_IMAGE_FORMAT_COMPRESSED_ATX : if ( ( nType == KD_IMAGE_TYPE_PVR && !Configuration::getInstance ( )->supportsPVRTC ( ) ) || ( nType == KD_IMAGE_TYPE_S3TC && !Configuration::getInstance ( )->supportsS3TC ( ) ) || ( nType == KD_IMAGE_TYPE_ATITC && !Configuration::getInstance ( )->supportsATITC ( ) ) || ( nType == KD_IMAGE_TYPE_ETC && !Configuration::getInstance ( )->supportsETC ( ) ) ) { eFormat = Texture2D::PixelFormat::RGBA8888; } else { eFormat = Texture2D::PixelFormat::COMPRESSED; } break; case KD_IMAGE_FORMAT_ALPHA8_ATX: eFormat = Texture2D::PixelFormat::A8; break; case KD_IMAGE_FORMAT_LUMINANCE_ATX: eFormat = Texture2D::PixelFormat::I8; break; case KD_IMAGE_FORMAT_LUMALPHA_ATX: eFormat = Texture2D::PixelFormat::AI88; break; case KD_IMAGE_FORMAT_PALETTED_ATX: eFormat = Texture2D::PixelFormat::RGB5A1; break; case KD_IMAGE_FORMAT_RGB_ATX: if ( nBpp == 24 || nBpp == 48 ) { eFormat = Texture2D::PixelFormat::RGB888; } else { eFormat = Texture2D::PixelFormat::RGB565; } break; case KD_IMAGE_FORMAT_RGBA_ATX: if ( nBpp == 16 ) { eFormat = ( nAlpha == 4 ) ? Texture2D::PixelFormat::RGBA4444 : Texture2D::PixelFormat::RGB5A1; } else { eFormat = Texture2D::PixelFormat::RGBA8888; } break; default: break; break; } } pImage = kdGetImageFromStreamATX ( pFile, (KDint) eFormat, KD_IMAGE_FLAG_PREMULTIPLIED_ALPHA ); CC_BREAK_IF ( !pImage ); m_eRenderFormat = (Texture2D::PixelFormat) kdGetImageIntATX ( pImage, KD_IMAGE_FORMAT_ATX ); m_nWidth = kdGetImageIntATX ( pImage, KD_IMAGE_WIDTH_ATX ); m_nHeight = kdGetImageIntATX ( pImage, KD_IMAGE_HEIGHT_ATX ); m_bHasPremultipliedAlpha = kdGetImageIntATX ( pImage, KD_IMAGE_FLAG_PREMULTIPLIED_ALPHA ) ? KD_TRUE : KD_FALSE; m_nDataLen = kdGetImageIntATX ( pImage, KD_IMAGE_DATASIZE_ATX ); m_nNumberOfMipmaps = kdGetImageIntATX ( pImage, KD_IMAGE_LEVELS_ATX ); m_pData = (KDubyte*) kdGetImagePointerATX ( pImage, KD_IMAGE_POINTER_BUFFER_ATX ); m_pImageAtx = pImage; for ( KDint i = 0; i < m_nNumberOfMipmaps; i++ ) { m_aMipmaps [ i ].address = m_pData + kdGetImageLevelIntATX ( pImage, KD_IMAGE_BUFFEROFFSET_ATX, i ); m_aMipmaps [ i ].len = kdGetImageLevelIntATX ( pImage, KD_IMAGE_DATASIZE_ATX, i ); } bRet = true; } while ( 0 ); if ( pFile ) { kdFclose ( pFile ); } if ( pUnpackedData != pData ) { kdFree ( pUnpackedData ); } } while ( 0 ); return bRet; }
KD_API KDImageATX KD_APIENTRY kdGetImageFromStreamATX(KDFile *file, KDint format, KDint flags) { _KDImageATX *image = (_KDImageATX *)kdMalloc(sizeof(_KDImageATX)); if(image == KD_NULL) { kdSetError(KD_ENOMEM); return KD_NULL; } image->levels = 0; image->bpp = 8; KDStat st; if(kdFstat(file, &st) == -1) { kdFree(image); kdSetError(KD_EIO); return KD_NULL; } void *filedata = kdMalloc((KDsize)st.st_size); if(filedata == KD_NULL) { kdFree(image); kdSetError(KD_ENOMEM); return KD_NULL; } if(kdFread(filedata, 1, (KDsize)st.st_size, file) != (KDsize)st.st_size) { kdFree(filedata); kdFree(image); kdSetError(KD_EIO); return KD_NULL; } if(kdFseek(file, 0, KD_SEEK_SET) == -1) { kdFree(filedata); kdFree(image); kdSetError(KD_EIO); return KD_NULL; } KDint channels = 0; image->format = format; switch(image->format) { case(KD_IMAGE_FORMAT_RGBA8888_ATX): { channels = 4; image->alpha = KD_TRUE; break; } case(KD_IMAGE_FORMAT_RGB888_ATX): { channels = 3; image->alpha = KD_FALSE; break; } case(KD_IMAGE_FORMAT_LUMALPHA88_ATX): { channels = 2; image->alpha = KD_TRUE; break; } case(KD_IMAGE_FORMAT_LUM8_ATX): { channels = 1; image->alpha = KD_FALSE; break; } case(KD_IMAGE_FORMAT_COMPRESSED_ATX): { /* TODO: Load compressed formats (do not decode) */ } default: { kdFree(filedata); kdFree(image); kdSetError(KD_EINVAL); return KD_NULL; } } if(kdStrstrVEN(file->pathname, ".pvr")) { if(channels == 4) { /* PVR v2 only*/ struct PVR_Texture_Header { KDuint dwHeaderSize; /* size of the structure */ KDuint dwHeight; /* height of surface to be created */ KDuint dwWidth; /* width of input surface */ KDuint dwMipMapCount; /* number of mip-map levels requested */ KDuint dwpfFlags; /* pixel format flags */ KDuint dwTextureDataSize; /* Total size in bytes */ KDuint dwBitCount; /* number of bits per pixel */ KDuint dwRBitMask; /* mask for red bit */ KDuint dwGBitMask; /* mask for green bits */ KDuint dwBBitMask; /* mask for blue bits */ KDuint dwAlphaBitMask; /* mask for alpha channel */ KDuint dwPVR; /* magic number identifying pvr file */ KDuint dwNumSurfs; /* the number of surfaces present in the pvr */ }; struct PVR_Texture_Header header; kdMemcpy(&header, filedata, sizeof(KDuint) * 13); image->height = (KDint)header.dwHeight; image->width = (KDint)header.dwWidth; image->size = (KDsize)image->width * (KDsize)image->height * (KDsize)channels * sizeof(KDuint); image->buffer = kdMalloc(image->size); /* PVRCT2/4 RGB/RGBA compressed formats for now */ __kdDecompressPVRTC((const KDuint8 *)filedata + header.dwHeaderSize, 0, image->width, image->height, image->buffer); } } else { if(flags == KD_IMAGE_FLAG_FLIP_X_ATX) { stbi_set_flip_vertically_on_load(1); } image->buffer = stbi_load_from_memory(filedata, (KDint)st.st_size, &image->width, &image->height, (KDint[]) {0}, channels); image->size = (KDsize)image->width * (KDsize)image->height * (KDsize)channels * sizeof(KDuint); } kdFree(filedata); if(image->buffer == KD_NULL) { kdLogMessagefKHR("%s.\n", stbi_failure_reason()); kdFree(image); kdSetError(KD_EILSEQ); return KD_NULL; } return image; }