Permalink
Browse files

add LoadImageFromMemory to cximage and use it to... load our images f…

…rom memory
  • Loading branch information...
1 parent 851d441 commit 68bb7ce4c79ab643457a1cffd35d3dd18ee5307d Jonathan Marshall committed Jul 8, 2011
Showing with 86 additions and 7 deletions.
  1. +74 −0 lib/cximage-6.0/CxImage/DllInterface.cpp
  2. +9 −7 xbmc/guilib/Texture.cpp
  3. +3 −0 xbmc/pictures/DllImageLib.h
@@ -285,6 +285,80 @@ extern "C"
return false;
}
+ __declspec(dllexport) bool LoadImageFromMemory(BYTE *buffer, unsigned int size, const char *ext, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
+ {
+ if (!buffer || !size || !ext) return false;
+ // load the image
+ DWORD dwImageType = CXIMAGE_FORMAT_UNKNOWN;
+ if (strlen(ext)) {
+ dwImageType = GetImageType(ext);
+ if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
+ dwImageType = DetectFileType(buffer, size);
+ }
+ else
+ dwImageType = DetectFileType(buffer, size);
+ if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
+ {
+ printf("PICTURE::LoadImageFromMemory: Unable to determine image type.");
+ return false;
+ }
+ CxImage *image = new CxImage(dwImageType);
+ if (!image) return false;
+
+ int actualwidth = maxwidth;
+ int actualheight = maxheight;
+
+ try
+ {
+ bool success = image->Decode(buffer, size, dwImageType);
+ if (!success && dwImageType != CXIMAGE_FORMAT_UNKNOWN)
+ { // try to decode with unknown imagetype
+ success = image->Decode(buffer, size, CXIMAGE_FORMAT_UNKNOWN);
+ }
+ if (!success || !image->IsValid())
+ {
+#if !defined(_LINUX) && !defined(__APPLE__)
+ int nErr = GetLastError();
+#else
+ int nErr = errno;
+#endif
+ printf("PICTURE::LoadImageFromMemory: Unable to decode image. Error:%s (%d)\n", image->GetLastError(), nErr);
+ delete image;
+ return false;
+ }
+ }
+ catch (...)
+ {
+ printf("PICTURE::LoadImageFromMemory: Unable to open image\n");
+ delete image;
+ return false;
+ }
+
+ // ok, now resample the image down if necessary
+ if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
+ {
+ printf("PICTURE::LoadImageFromMemory: Unable to resample picture\n");
+ delete image;
+ return false;
+ }
+
+ // make sure our image is 24bit minimum
+ image->IncreaseBpp(24);
+
+ // fill in our struct
+ info->width = image->GetWidth();
+ info->height = image->GetHeight();
+ info->originalwidth = actualwidth;
+ info->originalheight = actualheight;
+ memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
+
+ // create our texture
+ info->context = image;
+ info->texture = image->GetBits();
+ info->alpha = image->AlphaGetBits();
+ return (info->texture != NULL);
+ };
+
__declspec(dllexport) bool LoadImage(const char *file, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
{
if (!file || !info) return false;
View
@@ -26,9 +26,9 @@
#include "pictures/DllImageLib.h"
#include "DDSImage.h"
#include "filesystem/SpecialProtocol.h"
+#include "filesystem/File.h"
#if defined(__APPLE__) && defined(__arm__)
#include <ImageIO/ImageIO.h>
-#include "filesystem/File.h"
#include "osx/DarwinUtils.h"
#endif
@@ -170,9 +170,8 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxW
return false;
}
-#if defined(__APPLE__) && defined(__arm__)
XFILE::CFile file;
- UInt8 *imageBuff = NULL;
+ uint8_t *imageBuff = NULL;
int64_t imageBuffSize = 0;
//open path and read data to buffer
@@ -181,7 +180,7 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxW
if (file.Open(texturePath, 0))
{
imageBuffSize =file.GetLength();
- imageBuff = new UInt8[imageBuffSize];
+ imageBuff = new uint8_t[(size_t)imageBuffSize];
imageBuffSize = file.Read(imageBuff, imageBuffSize);
file.Close();
}
@@ -198,6 +197,7 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxW
return false;
}
+#if defined(__APPLE__) && defined(__arm__)
// create the image from buffer;
CGImageSourceRef imageSource;
// create a CFDataRef using CFDataCreateWithBytesNoCopy and kCFAllocatorNull for deallocator.
@@ -295,19 +295,20 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxW
CGContextRelease(context);
CGImageRelease(image);
CFRelease(cfdata);
- delete [] imageBuff;
#else
DllImageLib dll;
if (!dll.Load())
+ {
+ delete[] imageBuff;
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))
+ if(!dll.LoadImageFromMemory(imageBuff, (unsigned int)imageBuffSize, URIUtils::GetExtension(texturePath).c_str(), width, height, &image))
{
CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str());
return false;
@@ -362,6 +363,7 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxW
}
dll.ReleaseImage(&image);
#endif
+ delete [] imageBuff;
ClampToEdge();
@@ -92,6 +92,7 @@ class DllImageLibInterface
virtual ~DllImageLibInterface() {}
virtual bool ReleaseImage(ImageInfo *)=0;
virtual bool LoadImage(const char *, unsigned int, unsigned int, ImageInfo *)=0;
+ virtual bool LoadImageFromMemory(BYTE *, unsigned int, const char *, unsigned int, unsigned int, ImageInfo *)=0;
virtual bool CreateThumbnail(const char *, const char *, int, int, bool)=0;
virtual bool CreateThumbnailFromMemory(BYTE *, unsigned int, const char *, const char *, int, int)=0;
virtual bool CreateFolderThumbnail(const char **, const char *, int, int)=0;
@@ -104,6 +105,7 @@ class DllImageLib : public DllDynamic, DllImageLibInterface
DECLARE_DLL_WRAPPER(DllImageLib, DLL_PATH_IMAGELIB)
DEFINE_METHOD1(bool, ReleaseImage, (ImageInfo *p1))
DEFINE_METHOD4(bool, LoadImage, (const char * p1, unsigned int p2, unsigned int p3, ImageInfo * p4))
+ DEFINE_METHOD6(bool, LoadImageFromMemory, (BYTE *p1, unsigned int p2, const char * p3, unsigned int p4, unsigned int p5, ImageInfo * p6))
DEFINE_METHOD5(bool, CreateThumbnail, (const char * p1, const char * p2, int p3, int p4, bool p5))
DEFINE_METHOD6(bool, CreateThumbnailFromMemory, (BYTE *p1, unsigned int p2, const char * p3, const char * p4, int p5, int p6))
DEFINE_METHOD4(bool, CreateFolderThumbnail, (const char ** p1, const char * p2, int p3, int p4))
@@ -112,6 +114,7 @@ class DllImageLib : public DllDynamic, DllImageLibInterface
BEGIN_METHOD_RESOLVE()
RESOLVE_METHOD(ReleaseImage)
RESOLVE_METHOD(LoadImage)
+ RESOLVE_METHOD(LoadImageFromMemory)
RESOLVE_METHOD(CreateThumbnail)
RESOLVE_METHOD(CreateThumbnailFromMemory)
RESOLVE_METHOD(CreateFolderThumbnail)

2 comments on commit 68bb7ce

@Memphiz
Collaborator

I like that idea :D

@jmarshallnz
Owner

For jpegs it doesn't actually save all that much according to my timings, though it does have the advantage that we can more easily swap out image libraries (as the image lib no longer needs to be wrapped for file i/o).

Note that one slowness (if you're running on 720p for instance) with fanart would be that we downsample 1080p fanart to 720p. Removing that will probably make quite a difference - see DllInterface.cpp in cximage.

Please sign in to comment.