diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index b4f97f79fd761..5e9c23ece3315 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -43,6 +43,31 @@ extern "C" { using namespace XFILE; +bool CPicture::GetThumbnailFromSurface(const unsigned char* buffer, int width, int height, int stride, const std::string &thumbFile, uint8_t* &result, size_t& result_size) +{ + unsigned char *thumb = NULL; + unsigned int thumbsize = 0; + + // get an image handler + IImage* image = ImageFactory::CreateLoader(thumbFile); + if (image == NULL || !image->CreateThumbnailFromSurface((BYTE *)buffer, width, height, XB_FMT_A8R8G8B8, stride, thumbFile.c_str(), thumb, thumbsize)) + { + delete image; + return false; + } + + // copy the resulting buffer + result_size = thumbsize; + result = new uint8_t[result_size]; + memcpy(result, thumb, result_size); + + // release the image buffer and the image handler + image->ReleaseThumbnailBuffer(); + delete image; + + return true; +} + bool CPicture::CreateThumbnailFromSurface(const unsigned char *buffer, int width, int height, int stride, const std::string &thumbFile) { CLog::Log(LOGDEBUG, "cached image '%s' size %dx%d", thumbFile.c_str(), width, height); @@ -102,6 +127,75 @@ bool CThumbnailWriter::DoWork() return success; } +bool CPicture::ResizeTexture(const std::string &image, CBaseTexture *texture, uint32_t &dest_width, uint32_t &dest_height, uint8_t* &result, size_t& result_size) +{ + if (image.empty() || texture == NULL) + return false; + + return ResizeTexture(image, texture->GetPixels(), texture->GetWidth(), texture->GetHeight(), texture->GetPitch(), + dest_width, dest_height, result, result_size); +} + +bool CPicture::ResizeTexture(const std::string &image, uint8_t *pixels, uint32_t width, uint32_t height, uint32_t pitch, uint32_t &dest_width, uint32_t &dest_height, uint8_t* &result, size_t& result_size) +{ + if (image.empty() || pixels == NULL) + return false; + + dest_width = std::min(width, dest_width); + dest_height = std::min(height, dest_height); + + // if no max width or height is specified, don't resize + if (dest_width == 0 && dest_height == 0) + { + dest_width = width; + dest_height = height; + } + else if (dest_width == 0) + { + double factor = (double)dest_height / (double)height; + dest_width = (uint32_t)(width * factor); + } + else if (dest_height == 0) + { + double factor = (double)dest_width / (double)width; + dest_height = (uint32_t)(height * factor); + } + + // nothing special to do if the dimensions already match + if (dest_width >= width || dest_height >= height) + return GetThumbnailFromSurface(pixels, dest_width, dest_height, pitch, image, result, result_size); + + // create a buffer large enough for the resulting image + GetScale(width, height, dest_width, dest_height); + + uint8_t *buffer = new uint8_t[dest_width * dest_height * sizeof(uint32_t)]; + if (buffer == NULL) + { + result = NULL; + result_size = 0; + return false; + } + + if (!ScaleImage(pixels, width, height, pitch, buffer, dest_width, dest_height, dest_width * sizeof(uint32_t))) + { + delete[] buffer; + result = NULL; + result_size = 0; + return false; + } + + bool success = GetThumbnailFromSurface(buffer, dest_width, dest_height, dest_width * sizeof(uint32_t), image, result, result_size); + delete[] buffer; + + if (!success) + { + result = NULL; + result_size = 0; + } + + return success; +} + bool CPicture::CacheTexture(CBaseTexture *texture, uint32_t &dest_width, uint32_t &dest_height, const std::string &dest) { return CacheTexture(texture->GetPixels(), texture->GetWidth(), texture->GetHeight(), texture->GetPitch(), diff --git a/xbmc/pictures/Picture.h b/xbmc/pictures/Picture.h index 2eb041ac1d1e4..b332837012d10 100644 --- a/xbmc/pictures/Picture.h +++ b/xbmc/pictures/Picture.h @@ -27,6 +27,7 @@ class CBaseTexture; class CPicture { public: + static bool GetThumbnailFromSurface(const unsigned char* buffer, int width, int height, int stride, const std::string &thumbFile, uint8_t* &result, size_t& result_size); static bool CreateThumbnailFromSurface(const unsigned char* buffer, int width, int height, int stride, const std::string &thumbFile); /*! \brief Create a tiled thumb of the given files @@ -35,6 +36,9 @@ class CPicture */ static bool CreateTiledThumb(const std::vector &files, const std::string &thumb); + static bool ResizeTexture(const std::string &image, CBaseTexture *texture, uint32_t &dest_width, uint32_t &dest_height, uint8_t* &result, size_t& result_size); + static bool ResizeTexture(const std::string &image, uint8_t *pixels, uint32_t width, uint32_t height, uint32_t pitch, uint32_t &dest_width, uint32_t &dest_height, uint8_t* &result, size_t& result_size); + /*! \brief Cache a texture, resizing, rotating and flipping as needed, and saving as a JPG or PNG \param texture a pointer to a CBaseTexture \param dest_width [in/out] maximum width in pixels of cached version - replaced with actual cached width