bool CBaseTexture::LoadFromFileInternal(const std::string& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, bool requirePixels, const std::string& strMimeType) { if (URIUtils::HasExtension(texturePath, ".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); // Read image into memory to use our vfs XFILE::CFile file; XFILE::auto_buffer buf; if (file.LoadFile(texturePath, buf) <= 0) return false; CURL url(texturePath); // make sure resource:// paths are properly resolved if (url.IsProtocol("resource")) { std::string translatedPath; if (XFILE::CResourceFile::TranslatePath(url, translatedPath)) url.Parse(translatedPath); } // handle xbt:// paths differently because it allows loading the texture directly from memory if (url.IsProtocol("xbt")) { XFILE::CXbtFile xbtFile; if (!xbtFile.Open(url)) return false; return LoadFromMemory(xbtFile.GetImageWidth(), xbtFile.GetImageHeight(), 0, xbtFile.GetImageFormat(), xbtFile.HasImageAlpha(), reinterpret_cast<unsigned char*>(buf.get())); } IImage* pImage; if(strMimeType.empty()) pImage = ImageFactory::CreateLoader(texturePath); else pImage = ImageFactory::CreateLoaderFromMimeType(strMimeType); if (!LoadIImage(pImage, (unsigned char *)buf.get(), buf.size(), width, height, autoRotate)) { CLog::Log(LOGDEBUG, "%s - Load of %s failed.", __FUNCTION__, texturePath.c_str()); delete pImage; return false; } delete pImage; return true; }
void CompressToDDS(SDL_Surface* image, unsigned int format, CDDSImage &out) { // Convert to ARGB SDL_PixelFormat argbFormat; memset(&argbFormat, 0, sizeof(SDL_PixelFormat)); argbFormat.BitsPerPixel = 32; argbFormat.BytesPerPixel = 4; #if SDL_BYTEORDER == SDL_LIL_ENDIAN argbFormat.Amask = 0xff000000; argbFormat.Ashift = 24; argbFormat.Rmask = 0x00ff0000; argbFormat.Rshift = 16; argbFormat.Gmask = 0x0000ff00; argbFormat.Gshift = 8; argbFormat.Bmask = 0x000000ff; argbFormat.Bshift = 0; #else argbFormat.Amask = 0x000000ff; argbFormat.Ashift = 0; argbFormat.Rmask = 0x0000ff00; argbFormat.Rshift = 8; argbFormat.Gmask = 0x00ff0000; argbFormat.Gshift = 16; argbFormat.Bmask = 0xff000000; argbFormat.Bshift = 24; #endif SDL_Surface *argbImage = SDL_ConvertSurface(image, &argbFormat, 0); double colorMSE, alphaMSE; if (format == XB_FMT_DXT1) CompressImage((squish::u8 *)argbImage->pixels, image->w, image->h, out.GetData(), squish::kDxt1, colorMSE, alphaMSE); else if (format == XB_FMT_DXT5) CompressImage((squish::u8 *)argbImage->pixels, image->w, image->h, out.GetData(), squish::kDxt5, colorMSE, alphaMSE); // print some info about the resulting image printf("Size: %dx%d %s in %u bytes. Quality: %5.2f\n", image->w, image->h, GetFormatString(format), out.GetSize(), colorMSE); SDL_FreeSurface(argbImage); }
bool CBaseTexture::LoadFromFileInternal(const std::string& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, bool requirePixels, const std::string& strMimeType) { if (URIUtils::HasExtension(texturePath, ".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); // Read image into memory to use our vfs XFILE::CFile file; XFILE::auto_buffer buf; if (file.LoadFile(texturePath, buf) <= 0) return false; IImage* pImage; if(strMimeType.empty()) pImage = ImageFactory::CreateLoader(texturePath); else pImage = ImageFactory::CreateLoaderFromMimeType(strMimeType); if (!LoadIImage(pImage, (unsigned char *)buf.get(), buf.size(), width, height, autoRotate)) { delete pImage; pImage = ImageFactory::CreateFallbackLoader(texturePath); if (!LoadIImage(pImage, (unsigned char *)buf.get(), buf.size(), width, height)) { CLog::Log(LOGDEBUG, "%s - Load of %s failed.", __FUNCTION__, texturePath.c_str()); delete pImage; return false; } } delete pImage; return true; }
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight) { if (URIUtils::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } #if defined(__APPLE__) && defined(__arm__) XFILE::CFile file; UInt8 *imageBuff = NULL; int64_t imageBuffSize = 0; //open path and read data to buffer //this handles advancedsettings.xml pathsubstitution //and resulting networking if (file.Open(texturePath, 0)) { imageBuffSize =file.GetLength(); imageBuff = new UInt8[imageBuffSize]; imageBuffSize = file.Read(imageBuff, imageBuffSize); file.Close(); } else { CLog::Log(LOGERROR, "Texture manager unable to open file %s", texturePath.c_str()); return false; } if (imageBuffSize <= 0) { CLog::Log(LOGERROR, "Texture manager read texture file failed."); delete [] imageBuff; return false; } // create the image from buffer; CGImageSourceRef imageSource; // create a CFDataRef using CFDataCreateWithBytesNoCopy and kCFAllocatorNull for deallocator. // this allows us to do a nocopy reference and we handle the free of imageBuff CFDataRef cfdata = CFDataCreateWithBytesNoCopy(NULL, imageBuff, imageBuffSize, kCFAllocatorNull); imageSource = CGImageSourceCreateWithData(cfdata, NULL); if (imageSource == nil) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", CSpecialProtocol::TranslatePath(texturePath).c_str()); CFRelease(cfdata); delete [] imageBuff; return false; } CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); int rotate = 0; if (autoRotate) { // get the orientation of the image for displaying it correctly CFDictionaryRef imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(imageSource,0, NULL); if (imagePropertiesDictionary != nil) { CFNumberRef orientation = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyOrientation); if (orientation != nil) { int value = 0; CFNumberGetValue(orientation, kCFNumberIntType, &value); if (value) rotate = value - 1; } CFRelease(imagePropertiesDictionary); } } CFRelease(imageSource); unsigned int width = CGImageGetWidth(image); unsigned int height = CGImageGetHeight(image); m_hasAlpha = (CGImageGetAlphaInfo(image) != kCGImageAlphaNone); if (originalWidth) *originalWidth = width; if (originalHeight) *originalHeight = height; // check texture size limits and limit to screen size - preserving aspectratio of image if ( width > g_Windowing.GetMaxTextureSize() || height > g_Windowing.GetMaxTextureSize() ) { float aspect; if ( width > height ) { aspect = (float)width / (float)height; width = g_Windowing.GetWidth(); height = (float)width / (float)aspect; } else { aspect = (float)height / (float)width; height = g_Windowing.GetHeight(); width = (float)height / (float)aspect; } CLog::Log(LOGDEBUG, "Texture manager texture clamp:new texture size: %i x %i", width, height); } // use RGBA to skip swizzling Allocate(width, height, XB_FMT_RGBA8); m_orientation = rotate; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // hw convert jmpeg to RGBA CGContextRef context = CGBitmapContextCreate(m_pixels, width, height, 8, GetPitch(), colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); // Flip so that it isn't upside-down //CGContextTranslateCTM(context, 0, height); //CGContextScaleCTM(context, 1.0f, -1.0f); #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 CGContextClearRect(context, CGRectMake(0, 0, width, height)); #else #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 // (just a way of checking whether we're running in 10.5 or later) if (CGContextDrawLinearGradient == 0) CGContextClearRect(context, CGRectMake(0, 0, width, height)); else #endif CGContextSetBlendMode(context, kCGBlendModeCopy); #endif //CGContextSetBlendMode(context, kCGBlendModeCopy); CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); CGContextRelease(context); CGImageRelease(image); CFRelease(cfdata); delete [] imageBuff; #else DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } m_hasAlpha = NULL != image.alpha; Allocate(image.width, image.height, XB_FMT_A8R8G8B8); if (autoRotate && image.exifInfo.Orientation) m_orientation = image.exifInfo.Orientation - 1; if (originalWidth) *originalWidth = image.originalwidth; if (originalHeight) *originalHeight = image.originalheight; unsigned int dstPitch = GetPitch(); unsigned int srcPitch = ((image.width + 1)* 3 / 4) * 4; // bitmap row length is aligned to 4 bytes unsigned char *dst = m_pixels; unsigned char *src = image.texture + (m_imageHeight - 1) * srcPitch; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2 += 4, src2 += 3) { dst2[0] = src2[0]; dst2[1] = src2[1]; dst2[2] = src2[2]; dst2[3] = 0xff; } src -= srcPitch; dst += dstPitch; } if(image.alpha) { dst = m_pixels + 3; src = image.alpha + (m_imageHeight - 1) * m_imageWidth; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2+=4, src2++) *dst2 = *src2; src -= m_imageWidth; dst += dstPitch; } } dll.ReleaseImage(&image); #endif ClampToEdge(); return true; }
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight) { if (URIUtils::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } //ImageLib is sooo sloow for jpegs. Try our own decoder first. If it fails, fall back to ImageLib. if (URIUtils::GetExtension(texturePath).Equals(".jpg") || URIUtils::GetExtension(texturePath).Equals(".tbn")) { CJpegIO jpegfile; if (jpegfile.Open(texturePath, maxWidth, maxHeight)) { if (jpegfile.Width() > 0 && jpegfile.Height() > 0) { Allocate(jpegfile.Width(), jpegfile.Height(), XB_FMT_A8R8G8B8); if (jpegfile.Decode(m_pixels, GetPitch(), XB_FMT_A8R8G8B8)) { if (autoRotate && jpegfile.Orientation()) m_orientation = jpegfile.Orientation() - 1; m_hasAlpha=false; ClampToEdge(); return true; } } } } DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } m_hasAlpha = NULL != image.alpha; Allocate(image.width, image.height, XB_FMT_A8R8G8B8); if (autoRotate && image.exifInfo.Orientation) m_orientation = image.exifInfo.Orientation - 1; if (originalWidth) *originalWidth = image.originalwidth; if (originalHeight) *originalHeight = image.originalheight; unsigned int dstPitch = GetPitch(); unsigned int srcPitch = ((image.width + 1)* 3 / 4) * 4; // bitmap row length is aligned to 4 bytes unsigned char *dst = m_pixels; unsigned char *src = image.texture + (m_imageHeight - 1) * srcPitch; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2 += 4, src2 += 3) { dst2[0] = src2[0]; dst2[1] = src2[1]; dst2[2] = src2[2]; dst2[3] = 0xff; } src -= srcPitch; dst += dstPitch; } if(image.alpha) { dst = m_pixels + 3; src = image.alpha + (m_imageHeight - 1) * m_imageWidth; for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst2 = dst; unsigned char *src2 = src; for (unsigned int x = 0; x < m_imageWidth; x++, dst2+=4, src2++) *dst2 = *src2; src -= m_imageWidth; dst += dstPitch; } } dll.ReleaseImage(&image); ClampToEdge(); return true; }
bool CBaseTexture::LoadFromFileInternal(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate) { #if defined(HAS_OMXPLAYER) if (URIUtils::GetExtension(texturePath).Equals(".jpg") || URIUtils::GetExtension(texturePath).Equals(".tbn") /*|| URIUtils::GetExtension(texturePath).Equals(".png")*/) { COMXImage omx_image; if(omx_image.ReadFile(texturePath)) { // TODO: we only decode as half width and height. this is a workaround for the PI memory limitation if(omx_image.Decode(omx_image.GetWidth() / 2, omx_image.GetHeight() / 2)) { Allocate(omx_image.GetDecodedWidth(), omx_image.GetDecodedHeight(), XB_FMT_A8R8G8B8); if(!m_pixels) { CLog::Log(LOGERROR, "Texture manager (OMX) out of memory"); omx_image.Close(); return false; } m_originalWidth = omx_image.GetOriginalWidth(); m_originalHeight = omx_image.GetOriginalHeight(); m_hasAlpha = omx_image.IsAlpha(); if (autoRotate && omx_image.GetOrientation()) m_orientation = omx_image.GetOrientation() - 1; if(omx_image.GetDecodedData()) { int size = ( ( GetPitch() * GetRows() ) > omx_image.GetDecodedSize() ) ? omx_image.GetDecodedSize() : ( GetPitch() * GetRows() ); memcpy(m_pixels, (unsigned char *)omx_image.GetDecodedData(), size); } omx_image.Close(); return true; } else { omx_image.Close(); } } } #endif if (URIUtils::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } //ImageLib is sooo sloow for jpegs. Try our own decoder first. If it fails, fall back to ImageLib. if (URIUtils::GetExtension(texturePath).Equals(".jpg") || URIUtils::GetExtension(texturePath).Equals(".tbn")) { CJpegIO jpegfile; if (jpegfile.Open(texturePath, maxWidth, maxHeight)) { if (jpegfile.Width() > 0 && jpegfile.Height() > 0) { Allocate(jpegfile.Width(), jpegfile.Height(), XB_FMT_A8R8G8B8); if (jpegfile.Decode(m_pixels, GetPitch(), XB_FMT_A8R8G8B8)) { if (autoRotate && jpegfile.Orientation()) m_orientation = jpegfile.Orientation() - 1; m_hasAlpha=false; ClampToEdge(); return true; } } } CLog::Log(LOGDEBUG, "%s - Load of %s failed. Falling back to ImageLib", __FUNCTION__, texturePath.c_str()); } DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } LoadFromImage(image, autoRotate); dll.ReleaseImage(&image); return true; }
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight) { if (URIUtils::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; if (image.ReadFile(texturePath)) { Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } return false; } //ImageLib is sooo sloow for jpegs. Try our own decoder first. If it fails, fall back to ImageLib. if (URIUtils::GetExtension(texturePath).Equals(".jpg") || URIUtils::GetExtension(texturePath).Equals(".tbn")) { CJpegIO jpegfile; if (jpegfile.Open(texturePath, maxWidth, maxHeight)) { if (jpegfile.Width() > 0 && jpegfile.Height() > 0) { Allocate(jpegfile.Width(), jpegfile.Height(), XB_FMT_A8R8G8B8); if (jpegfile.Decode(m_pixels, GetPitch(), XB_FMT_A8R8G8B8)) { if (autoRotate && jpegfile.Orientation()) m_orientation = jpegfile.Orientation() - 1; m_hasAlpha=false; ClampToEdge(); return true; } } } CLog::Log(LOGDEBUG, "%s - Load of %s failed. Falling back to ImageLib", __FUNCTION__, texturePath.c_str()); } DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } if (originalWidth) *originalWidth = image.originalwidth; if (originalHeight) *originalHeight = image.originalheight; LoadFromImage(image, autoRotate); dll.ReleaseImage(&image); return true; }
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight, unsigned int dstWidth, unsigned int dstHeight) { //Quick and dirty check if the file is DDS file... CFile file; if (!file.Open(texturePath)) { CLog::Log(LOGERROR, "%s - Error opening texture file: %s", __FUNCTION__, texturePath.c_str()); return false; } // read the header uint32_t magic; if (file.Read(&magic, 4) != 4) { CLog::Log(LOGERROR, "%s - Can't read signature from file: %s", __FUNCTION__, texturePath.c_str()); return false; } if (strncmp((const char *)&magic, "DDS ", 4) == 0 || CUtil::GetExtension(texturePath).Equals(".dds")) { // special case for DDS images CDDSImage image; CLog::Log(LOGDEBUG, "%s - loading dds file: %s", __FUNCTION__, texturePath.c_str()); image.ReadFile(texturePath); Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false); return true; } DllImageLib dll; if (!dll.Load()) return false; ImageInfo image; memset(&image, 0, sizeof(image)); //image.width = dstWidth; //image.height = dstHeight; unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize(); if(!dll.LoadImage(texturePath.c_str(), width, height, &image)) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } Allocate(image.width, image.height, XB_FMT_B8G8R8A8); if (autoRotate && image.exifInfo.Orientation) m_orientation = image.exifInfo.Orientation - 1; if (originalWidth) *originalWidth = image.originalwidth; if (originalHeight) *originalHeight = image.originalheight; unsigned int destPitch = GetPitch(); unsigned int srcPitch = ((image.width + 1)* 3 / 4) * 4; // bitmap row length is aligned to 4 bytes // test background color for alpha blending long nBkgndIndex; RGBQUAD nBkgndColor; dll.GetBackgroundColor(&image, &nBkgndColor, &nBkgndIndex); for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst = m_pixels + y * destPitch; unsigned char *src = image.texture + (m_imageHeight - 1 - y) * srcPitch; unsigned char *alpha = image.alpha + (m_imageHeight - 1 - y) * m_imageWidth; for (unsigned int x = 0; x < m_imageWidth; x++) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = (image.alpha) ? *alpha++ : 0xff; } } if (nBkgndIndex != -1) { for (unsigned int y = 0; y < m_imageHeight; y++) { unsigned char *dst = m_pixels + y * destPitch; //unsigned char *src = image.texture + (m_imageHeight - 1 - y) * srcPitch; //unsigned char *alpha = image.alpha + (m_imageHeight - 1 - y) * m_imageWidth; for (unsigned int x = 0; x < m_imageWidth; x++) { if (*dst == nBkgndColor.rgbBlue && *(dst + 1) == nBkgndColor.rgbGreen && *(dst + 2) == nBkgndColor.rgbRed) { *(dst + 3) = 0x00; } dst += 4; } } } dll.ReleaseImage(&image); ClampToEdge(); return true; }