summaryrefslogtreecommitdiff
path: root/libcore
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2014-11-15 11:15:48 +0100
committerlouis <louis.braun@gmx.de>2014-11-15 11:15:48 +0100
commit0ed710a86884136a7bd772322f13f0b176a5dc22 (patch)
treecd4ae6f14b29988d35ce67acb9012c610348bc95 /libcore
parentf225c38103013faf38512cc61362cf9bb9088ba6 (diff)
parent7a69d868c422218817f1c92a6666ee6c83825d23 (diff)
downloadvdr-plugin-skindesigner-0.0.5.tar.gz
vdr-plugin-skindesigner-0.0.5.tar.bz2
Version 0.0.5 - added SVG Support0.0.5
Diffstat (limited to 'libcore')
-rw-r--r--libcore/imagecache.c76
-rw-r--r--libcore/imagecache.h7
-rw-r--r--libcore/imageloader.c392
-rw-r--r--libcore/imageloader.h81
-rw-r--r--libcore/imagemagickwrapper.c162
-rw-r--r--libcore/imagemagickwrapper.h28
-rw-r--r--libcore/imagescaler.c149
-rw-r--r--libcore/imagescaler.h97
8 files changed, 470 insertions, 522 deletions
diff --git a/libcore/imagecache.c b/libcore/imagecache.c
index 9ad9918..369322e 100644
--- a/libcore/imagecache.c
+++ b/libcore/imagecache.c
@@ -7,14 +7,13 @@
#include "../config.h"
#include "helpers.h"
-using namespace Magick;
cMutex cImageCache::mutex;
string cImageCache::items[16] = { "Schedule", "Channels", "Timers", "Recordings", "Setup", "Commands",
"OSD", "EPG", "DVB", "LNB", "CAM", "Recording", "Replay", "Miscellaneous", "Plugins", "Restart"};
-cImageCache::cImageCache() : cImageMagickWrapper() {
+cImageCache::cImageCache() {
tempStaticLogo = NULL;
}
@@ -141,27 +140,19 @@ bool cImageCache::LogoExists(string channelID) {
if (!channel)
return false;
string logoLower = StrToLowerCase(channel->Name());
- string logoExt = *config.logoExtension;
- bool logoExists = FileExists(logoPath.c_str(), logoLower, logoExt);
- if (logoExists) {
- return true;
- }
- logoExists = FileExists(logoPath.c_str(), channelID, logoExt);
- if (logoExists) {
- return true;
- }
- return false;
+
+ return (FileExists(logoPath.c_str(), logoLower, "svg") ||
+ FileExists(logoPath.c_str(), logoLower, "png") ||
+ FileExists(logoPath.c_str(), channelID, "svg") ||
+ FileExists(logoPath.c_str(), channelID, "png"));
}
bool cImageCache::SeparatorLogoExists(string name) {
string separatorPath = *cString::sprintf("%sseparatorlogos/", logoPath.c_str());
string nameLower = StrToLowerCase(name.c_str());
- string logoExt = *config.logoExtension;
- bool logoExists = FileExists(separatorPath, nameLower, logoExt);
- if (logoExists) {
- return true;
- }
- return false;
+
+ return (FileExists(separatorPath, nameLower, "svg") ||
+ FileExists(separatorPath, nameLower, "png"));
}
void cImageCache::CacheIcon(eImageType type, string name, int width, int height) {
@@ -312,18 +303,17 @@ cImage *cImageCache::GetSkinpart(string name, int width, int height) {
}
bool cImageCache::LoadIcon(eImageType type, string name) {
- bool success = false;
cString subdir("");
if (type == itMenuIcon)
subdir = "menuicons";
else if (type == itIcon)
subdir = "icons";
cString subIconPath = cString::sprintf("%s%s/", iconPath.c_str(), *subdir);
- success = LoadImage(name, *subIconPath, "png");
- if (success) {
- return true;
- }
- return false;
+
+ if (FileExists(*subIconPath, name, "svg"))
+ return LoadImage(*subIconPath, name, "svg");
+ else
+ return LoadImage(*subIconPath, name, "png");
}
bool cImageCache::LoadLogo(const cChannel *channel) {
@@ -331,33 +321,33 @@ bool cImageCache::LoadLogo(const cChannel *channel) {
return false;
string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
string logoLower = StrToLowerCase(channel->Name());
- bool success = false;
- success = LoadImage(channelID.c_str(), logoPath.c_str(), *config.logoExtension);
- if (success)
- return true;
- success = LoadImage(logoLower.c_str(), logoPath.c_str(), *config.logoExtension);
- if (success)
- return true;
+
+ if (FileExists(logoPath.c_str(), channelID.c_str(), "svg"))
+ return LoadImage(logoPath.c_str(), channelID.c_str(), "svg");
+ if (FileExists(logoPath.c_str(), channelID.c_str(), "png"))
+ return LoadImage(logoPath.c_str(), channelID.c_str(), "png");
+ if (FileExists(logoPath.c_str(), logoLower.c_str(), "svg"))
+ return LoadImage(logoPath.c_str(), logoLower.c_str(), "svg");
+ if (FileExists(logoPath.c_str(), logoLower.c_str(), "png"))
+ return LoadImage(logoPath.c_str(), logoLower.c_str(), "png");
+
return false;
}
bool cImageCache::LoadSeparatorLogo(string name) {
- cString separatorPath = cString::sprintf("%sseparatorlogos/", logoPath.c_str());
+ string separatorPath = *cString::sprintf("%sseparatorlogos/", logoPath.c_str());
string nameLower = StrToLowerCase(name.c_str());
- bool success = false;
- success = LoadImage(nameLower.c_str(), *separatorPath, *config.logoExtension);
- if (success)
- return true;
- return false;
+ if (FileExists(separatorPath, nameLower.c_str(), "svg"))
+ return LoadImage(separatorPath, nameLower.c_str(), "svg");
+ else
+ return LoadImage(separatorPath, nameLower.c_str(), "png");
}
bool cImageCache::LoadSkinpart(string name) {
- bool success = false;
- success = LoadImage(name, skinPartsPath.c_str(), "png");
- if (success) {
- return true;
- }
- return false;
+ if (FileExists(skinPartsPath.c_str(), name, "svg"))
+ return LoadImage(skinPartsPath.c_str(), name, "svg");
+ else
+ return LoadImage(skinPartsPath.c_str(), name, "png");
}
void cImageCache::Clear(void) {
diff --git a/libcore/imagecache.h b/libcore/imagecache.h
index db56a67..4e88600 100644
--- a/libcore/imagecache.h
+++ b/libcore/imagecache.h
@@ -5,14 +5,11 @@
#include <vdr/osd.h>
#include <vdr/skins.h>
-#include <Magick++.h>
#include <vector>
-#include "imagemagickwrapper.h"
+#include "imageloader.h"
#include "../libtemplate/templatefunction.h"
-using namespace Magick;
-
-class cImageCache : public cImageMagickWrapper {
+class cImageCache : public cImageLoader {
public:
cImageCache();
~cImageCache();
diff --git a/libcore/imageloader.c b/libcore/imageloader.c
index 61e8076..139e2d0 100644
--- a/libcore/imageloader.c
+++ b/libcore/imageloader.c
@@ -1,62 +1,400 @@
#include "../config.h"
#include "helpers.h"
#include "imageloader.h"
-#include <math.h>
#include <string>
#include <dirent.h>
#include <iostream>
-using namespace Magick;
-
-cImageLoader::cImageLoader() : cImageMagickWrapper() {
+cImageLoader::cImageLoader() {
+ importer = NULL;
}
cImageLoader::~cImageLoader() {
+ delete(importer);
}
-cImage cImageLoader::GetImage() {
- return CreateImageCopy();
-}
+cImage *cImageLoader::CreateImage(int width, int height, bool preserveAspect) {
+ if (!importer)
+ return NULL;
+
+ int w, h;
+ importer->GetImageSize(w, h);
+ if (width == 0)
+ width = w;
+ if (height == 0)
+ height = h;
+
+ cairo_surface_t *surface;
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
-bool cImageLoader::LoadImage(const char *path, int width, int height) {
- if (cImageMagickWrapper::LoadImage(path)) {
- buffer.sample(Geometry(width, height));
- return true;
+ cairo_t *cr;
+ cr = cairo_create(surface);
+
+ double sx = width / (double)w;
+ double sy = height / (double)h;
+ if (preserveAspect) {
+ double tx = 0;
+ double ty = 0;
+ if (sx < sy) {
+ sy = sx;
+ ty = (height - h * sy) / 2;
+ }
+ if (sy < sx) {
+ sx = sy;
+ tx = (width - w * sx) / 2;
+ }
+ cairo_translate(cr, tx, ty);
}
- return false;
+ cairo_scale(cr, sx, sy);
+
+ importer->DrawToCairo(cr);
+
+ cairo_status_t status = cairo_status(cr);
+ if (status && config.debugImageLoading)
+ dsyslog("skindesigner: Cairo CreateImage Error %s", cairo_status_to_string(status));
+
+ unsigned char *data = cairo_image_surface_get_data(surface);
+ cImage *image = new cImage(cSize(width, height), (tColor*)data);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ return image;
+}
+
+bool cImageLoader::LoadImage(const char *fullpath) {
+ if ((fullpath == NULL) || (strlen(fullpath) < 5))
+ return false;
+
+ if (config.debugImageLoading)
+ dsyslog("skindesigner: trying to load: %s", fullpath);
+
+ delete(importer);
+ importer = NULL;
+
+ if (endswith(fullpath, ".png"))
+ importer = new cImageImporterPNG;
+ else if (endswith(fullpath, ".svg"))
+ importer = new cImageImporterSVG;
+ else if (endswith(fullpath, ".jpg"))
+ importer = new cImageImporterJPG;
+ else
+ return false;
+
+ return importer->LoadImage(fullpath);
+}
+
+// Just a different way to call LoadImage. Calls the above one.
+bool cImageLoader::LoadImage(std::string Path, std::string FileName, std::string Extension) {
+ std::stringstream sstrImgFile;
+ sstrImgFile << Path << FileName << "." << Extension;
+ std::string imgFile = sstrImgFile.str();
+ return LoadImage(imgFile.c_str());
}
void cImageLoader::DeterminateChannelLogoSize(int &width, int &height) {
cString logoPath;
cString logoPathSkin = cString::sprintf("%s%s/themes/%s/logos/", *config.skinPath, Setup.OSDSkin, Setup.OSDTheme);
- if (FolderExists(*logoPathSkin)) {
+
+ if (FolderExists(*logoPathSkin))
logoPath = logoPathSkin;
- } else {
+ else
logoPath = config.logoPath;
- }
- cString logoExt = config.logoExtension;
+
DIR *folder = NULL;
struct dirent *file;
folder = opendir(logoPath);
- if (!folder) {
+ if (!folder)
return;
- }
- while (file = readdir(folder)) {
- if (endswith(file->d_name, *logoExt)) {
+
+ while ( (file = readdir(folder)) ) {
+ if (endswith(file->d_name, ".png") ||
+ endswith(file->d_name, ".svg")) {
std::stringstream filePath;
filePath << *logoPath << file->d_name;
- Image logo;
- try {
- logo.read(filePath.str().c_str());
- Geometry g = logo.size();
- int logoWidth = g.width();
- int logoHeight = g.height();
+ if (LoadImage(filePath.str().c_str())) {
+ int logoWidth = 0;
+ int logoHeight = 0;
+ importer->GetImageSize(logoWidth, logoHeight);
if (logoWidth > 0 && logoHeight > 0) {
width = logoWidth;
height = logoHeight;
+ delete(importer);
+ importer = NULL;
return;
}
- } catch( ... ) { }
+ }
+ }
+ }
+}
+
+
+//
+// Image importer for PNG
+//
+
+cImageImporterPNG::cImageImporterPNG() {
+ surface = NULL;
+}
+
+cImageImporterPNG::~cImageImporterPNG() {
+ if (surface)
+ cairo_surface_destroy(surface);
+}
+
+bool cImageImporterPNG::LoadImage(const char *path) {
+ if (surface)
+ cairo_surface_destroy(surface);
+
+ surface = cairo_image_surface_create_from_png(path);
+
+ if (cairo_surface_status(surface)) {
+ if (config.debugImageLoading)
+ dsyslog("skindesigner: Cairo LoadImage Error: %s", cairo_status_to_string(cairo_surface_status(surface)));
+ surface = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+void cImageImporterPNG::DrawToCairo(cairo_t *cr) {
+ if (surface) {
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_paint(cr);
+ }
+}
+
+void cImageImporterPNG::GetImageSize(int &width, int &height) {
+ if (surface) {
+ width = cairo_image_surface_get_width(surface);
+ height = cairo_image_surface_get_height(surface);
+ }
+}
+
+//
+// Image importer for SVG
+//
+
+cImageImporterSVG::cImageImporterSVG() {
+ handle = NULL;
+}
+
+cImageImporterSVG::~cImageImporterSVG() {
+ if (handle) {
+ rsvg_handle_close(handle, NULL);
+ g_object_unref(handle);
+ }
+}
+
+bool cImageImporterSVG::LoadImage(const char *path) {
+ if (handle) {
+ rsvg_handle_close(handle, NULL);
+ g_object_unref(handle);
+ }
+
+ GError *error = NULL;
+ handle = rsvg_handle_new_from_file(path, &error);
+ if (!handle) {
+ if (config.debugImageLoading && error) {
+ dsyslog("skindesigner: RSVG Error: %s", error->message);
}
+ return false;
+ }
+
+ // 90 dpi is the hardcoded default setting of the Inkscape SVG editor
+ rsvg_handle_set_dpi(handle, 90);
+
+ return true;
+}
+
+void cImageImporterSVG::DrawToCairo(cairo_t *cr) {
+ if (handle)
+ rsvg_handle_render_cairo(handle, cr);
+}
+
+void cImageImporterSVG::GetImageSize(int &width, int &height) {
+ if (handle) {
+ RsvgDimensionData dim;
+ rsvg_handle_get_dimensions(handle, &dim);
+ width = dim.width;
+ height = dim.height;
+ }
+}
+
+//
+// Image importer for JPG
+//
+
+struct my_error_mgr {
+ struct jpeg_error_mgr pub; // "public" fields
+ jmp_buf setjmp_buffer; // for return to caller
+};
+
+METHODDEF(void)
+my_error_exit(j_common_ptr cinfo) {
+ // cinfo->err really points to a my_error_mgr struct, so coerce pointer
+ my_error_mgr *myerr = (my_error_mgr*) cinfo->err;
+
+ // Always display the message.
+ (*cinfo->err->output_message) (cinfo);
+
+ // Return control to the setjmp point
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+METHODDEF(void)
+my_output_message(j_common_ptr cinfo) {
+ char buf[JMSG_LENGTH_MAX];
+ cinfo->err->format_message(cinfo, buf);
+ if (config.debugImageLoading)
+ dsyslog("skindesigner: libjpeg error: %s", buf);
+}
+
+cImageImporterJPG::cImageImporterJPG() {
+ cinfo = NULL;
+}
+
+cImageImporterJPG::~cImageImporterJPG() {
+ if (cinfo) {
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ fclose(infile);
+ }
+}
+
+bool cImageImporterJPG::LoadImage(const char *path) {
+ if (cinfo) {
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ fclose(infile);
+ cinfo = NULL;
+ }
+
+ // Open input file
+ if ((infile = fopen(path, "rb")) == NULL) {
+ if (config.debugImageLoading)
+ dsyslog("skindesigner: Can't open %s", path);
+ return false;
+ }
+
+ // Allocate space for our decompress struct
+ cinfo = (j_decompress_ptr)malloc(sizeof(struct jpeg_decompress_struct));
+
+ // We set up the normal JPEG error routines, then override error_exit
+ // and output_message.
+ struct my_error_mgr jerr;
+ cinfo->err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+ // Establish the setjmp return context for my_error_exit to use.
+ if (setjmp(jerr.setjmp_buffer)) {
+ // If we get here, the JPEG code has signaled an error.
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ fclose(infile);
+ cinfo = NULL;
+ return false;
+ }
+
+ // Now we can initialize the JPEG decompression object.
+ jpeg_create_decompress(cinfo);
+
+ // Step 2: specify data source (eg, a file)
+ jpeg_stdio_src(cinfo, infile);
+
+ // Step 3: read file parameters with jpeg_read_header()
+ (void) jpeg_read_header(cinfo, TRUE);
+ return true;
+}
+
+void cImageImporterJPG::DrawToCairo(cairo_t *cr) {
+ if (!cinfo)
+ return;
+
+ unsigned char *bmp_buffer = NULL;
+
+ // Re-establish error handling. We have to do this again as the saved
+ // calling environment of "LoadImage" is invalid if we reach here!
+ struct my_error_mgr jerr;
+ cinfo->err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+ if (setjmp(jerr.setjmp_buffer)) {
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ fclose(infile);
+ free(bmp_buffer);
+ cinfo = NULL;
+ return;
+ }
+
+ // Step 4: set parameters for decompression
+ cinfo->out_color_space = JCS_RGB;
+
+ // Step 5: Start decompressor
+ (void) jpeg_start_decompress(cinfo);
+
+ // Allocate buffer. Directly allocate the space needed for ARGB
+ unsigned int width = cinfo->output_width;
+ unsigned int height = cinfo->output_height;
+ bmp_buffer = (unsigned char*)malloc(width * height * 4);
+
+ // Step 6: while (scan lines remain to be read)
+ int jpg_stride = width * cinfo->output_components;
+ while (cinfo->output_scanline < height) {
+ unsigned char *buffer_array[1];
+ buffer_array[0] = bmp_buffer + (cinfo->output_scanline) * jpg_stride;
+ jpeg_read_scanlines(cinfo, buffer_array, 1);
+ }
+
+ // Step 7: Finish decompression.
+ (void)jpeg_finish_decompress(cinfo);
+
+ // Cleanup. In this "ImageImporter" we clean up everything in "DrawToCairo"
+ // as I'm not really sure whether we are able to draw a second time.
+ fclose(infile);
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ cinfo = NULL;
+
+ // --> At this point we have raw RGB data in bmp_buffer
+
+ // Do some ugly byte shifting.
+ // Byte order in libjpeg: RGB
+ // Byte order in cairo and VDR: BGRA
+ unsigned char temp[3];
+ for (int index = (width * height) - 1; index >= 0; index--) {
+ unsigned char *target = bmp_buffer + (index * 4);
+ unsigned char *source = bmp_buffer + (index * 3);
+ memcpy(&temp[0], source + 2, 1);
+ memcpy(&temp[1], source + 1, 1);
+ memcpy(&temp[2], source, 1);
+ memcpy(target, &temp, 3);
+ }
+
+ // Create new Cairo surface from our raw image data
+ cairo_surface_t *surface;
+ surface = cairo_image_surface_create_for_data(bmp_buffer,
+ CAIRO_FORMAT_RGB24,
+ width,
+ height,
+ width * 4);
+
+ // Draw surface to Cairo
+ if (surface) {
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_paint(cr);
+ cairo_surface_destroy(surface);
+ }
+
+ // Free our memory
+ free(bmp_buffer);
+}
+
+void cImageImporterJPG::GetImageSize(int &width, int &height) {
+ if (cinfo) {
+ width = cinfo->image_width;
+ height = cinfo->image_height;
}
}
diff --git a/libcore/imageloader.h b/libcore/imageloader.h
index 2a148be..a06f433 100644
--- a/libcore/imageloader.h
+++ b/libcore/imageloader.h
@@ -1,23 +1,82 @@
#ifndef __NOPACITY_IMAGELOADER_H
#define __NOPACITY_IMAGELOADER_H
-#define X_DISPLAY_MISSING
-
+#include <cairo.h>
+#include <librsvg/rsvg.h>
+#ifndef LIBRSVG_VERSION // Workaround for librsvg < 2.36.2
+ #include <librsvg/rsvg-cairo.h>
+#endif
+#include <jpeglib.h>
+#include <setjmp.h>
#include <vdr/osd.h>
-#include <vdr/skins.h>
-#include <Magick++.h>
-#include "imagemagickwrapper.h"
+#include <vdr/tools.h>
+
+//
+// Image importers
+//
+class cImageImporter {
+public:
+ cImageImporter() {};
+ virtual ~cImageImporter() {};
+ virtual bool LoadImage(const char *path) { return false; };
+ virtual void DrawToCairo(cairo_t *cr) {};
+ virtual void GetImageSize(int &width, int &height) {};
+};
+
+// Image importer for PNG
+class cImageImporterPNG : public cImageImporter {
+public:
+ cImageImporterPNG();
+ ~cImageImporterPNG();
+ bool LoadImage(const char *path);
+ void DrawToCairo(cairo_t *cr);
+ void GetImageSize(int &width, int &height);
+private:
+ cairo_surface_t *surface;
+};
+
+// Image importer for SVG
+class cImageImporterSVG : public cImageImporter {
+public:
+ cImageImporterSVG();
+ ~cImageImporterSVG();
+ bool LoadImage(const char *path);
+ void DrawToCairo(cairo_t *cr);
+ void GetImageSize(int &width, int &height);
+private:
+ RsvgHandle *handle;
+};
-using namespace Magick;
+// Image importer for JPG
+#if BITS_IN_JSAMPLE != 8
+ #error libjpeg has to be compiled with 8-bit samples!
+#endif
-class cImageLoader : public cImageMagickWrapper {
+class cImageImporterJPG : public cImageImporter {
+public:
+ cImageImporterJPG();
+ ~cImageImporterJPG();
+ bool LoadImage(const char *path);
+ void DrawToCairo(cairo_t *cr);
+ void GetImageSize(int &width, int &height);
+private:
+ j_decompress_ptr cinfo;
+ FILE *infile;
+};
+
+//
+// Image loader class
+//
+class cImageLoader {
+private:
+ cImageImporter *importer;
public:
cImageLoader();
- ~cImageLoader();
- cImage GetImage();
- bool LoadImage(const char *path, int width, int height);
+ virtual ~cImageLoader();
+ cImage *CreateImage(int width, int height, bool preserveAspect = true);
+ bool LoadImage(std::string Path, std::string FileName, std::string Extension);
+ bool LoadImage(const char *fullpath);
void DeterminateChannelLogoSize(int &width, int &height);
-private:
};
#endif //__NOPACITY_IMAGELOADER_H
diff --git a/libcore/imagemagickwrapper.c b/libcore/imagemagickwrapper.c
deleted file mode 100644
index ab1bcba..0000000
--- a/libcore/imagemagickwrapper.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <string>
-#include <sstream>
-#include "imagemagickwrapper.h"
-#include "../config.h"
-#include "imagescaler.h"
-
-cImageMagickWrapper::cImageMagickWrapper() {
- InitializeMagick(NULL);
-}
-
-cImageMagickWrapper::~cImageMagickWrapper() {
-}
-
-cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) {
- int w, h;
- w = buffer.columns();
- h = buffer.rows();
- if (width == 0)
- width = w;
- if (height == 0)
- height = h;
- if (preserveAspect) {
- unsigned scale_w = 1000 * width / w;
- unsigned scale_h = 1000 * height / h;
- if (scale_w > scale_h)
- width = w * height / h;
- else
- height = h * width / w;
- }
- const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
- cImage *image = new cImage(cSize(width, height));
- tColor *imgData = (tColor *)image->Data();
- if (w != width || h != height) {
- ImageScaler scaler;
- scaler.SetImageParameters(imgData, width, width, height, w, h);
- for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
- scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
- pixels->green / ((MaxRGB + 1) / 256),
- pixels->red / ((MaxRGB + 1) / 256),
- ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
- return image;
- }
- for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
- *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
- (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
- (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
- (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
- return image;
-}
-
-cImage cImageMagickWrapper::CreateImageCopy() {
- int w, h;
- w = buffer.columns();
- h = buffer.rows();
- cImage image (cSize(w, h));
- const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
- for (int iy = 0; iy < h; ++iy) {
- for (int ix = 0; ix < w; ++ix) {
- tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
- | (int(pixels->green * 255 / MaxRGB) << 8)
- | (int(pixels->red * 255 / MaxRGB) << 16)
- | (int(pixels->blue * 255 / MaxRGB) );
- image.SetPixel(cPoint(ix, iy), col);
- ++pixels;
- }
- }
- return image;
-}
-
-bool cImageMagickWrapper::LoadImage(std::string FileName, std::string Path, std::string Extension) {
- try {
- std::stringstream sstrImgFile;
- sstrImgFile << Path << FileName << "." << Extension;
- std::string imgFile = sstrImgFile.str();
- if (config.debugImageLoading)
- dsyslog("skindesigner: trying to load: %s", imgFile.c_str());
- buffer.read(imgFile.c_str());
- if (config.debugImageLoading)
- dsyslog("skindesigner: %s sucessfully loaded", imgFile.c_str());
- } catch( Magick::Warning &warning ) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: Magick Warning: %s", warning.what());
- return true;
- } catch( Magick::Error &error ) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: Magick Error: %s", error.what());
- return false;
- } catch(...) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: an unknown Magick error occured during image loading");
- return false;
- }
- return true;
-}
-
-bool cImageMagickWrapper::LoadImage(const char *fullpath) {
- if ((fullpath == NULL) || (strlen(fullpath) < 5))
- return false;
- try {
- if (config.debugImageLoading)
- dsyslog("skindesigner: trying to load: %s", fullpath);
- buffer.read(fullpath);
- if (config.debugImageLoading)
- dsyslog("skindesigner: %s sucessfully loaded", fullpath);
- } catch( Magick::Warning &warning ) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: Magick Warning: %s", warning.what());
- return true;
- } catch( Magick::Error &error ) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: Magick Error: %s", error.what());
- return false;
- } catch(...) {
- if (config.debugImageLoading)
- dsyslog("skindesigner: an unknown Magick error occured during image loading");
- return false;
- }
- return true;
-}
-
-Color cImageMagickWrapper::Argb2Color(tColor col) {
- tIndex alpha = (col & 0xFF000000) >> 24;
- tIndex red = (col & 0x00FF0000) >> 16;
- tIndex green = (col & 0x0000FF00) >> 8;
- tIndex blue = (col & 0x000000FF);
- Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
- return color;
-}
-
-void cImageMagickWrapper::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
- Color Back = Argb2Color(back);
- Color Blend = Argb2Color(blend);
- int maxw = MaxRGB * wfactor;
- int maxh = MaxRGB * hfactor;
-
- Image imgblend(Geometry(width, height), Blend);
- imgblend.modifyImage();
- imgblend.type(TrueColorMatteType);
- PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- PixelPacket *pixel = pixels + y * width + x;
- int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
- pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
- }
- }
- imgblend.syncPixels();
-
- Image imgback(Geometry(width, height), Back);
- imgback.composite(imgblend, 0, 0, OverCompositeOp);
-
- buffer = imgback;
-}
-
-void cImageMagickWrapper::CreateBackground(tColor back, tColor blend, int width, int height, bool mirror) {
- CreateGradient(back, blend, width, height, 0.8, 0.8);
- if (mirror)
- buffer.flop();
-}
-void cImageMagickWrapper::CreateBackgroundReverse(tColor back, tColor blend, int width, int height) {
- CreateGradient(back, blend, width, height, 1.3, 0.7);
-}
diff --git a/libcore/imagemagickwrapper.h b/libcore/imagemagickwrapper.h
deleted file mode 100644
index 5f9901e..0000000
--- a/libcore/imagemagickwrapper.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __NOPACITY_IMAGEMAGICKWRAPPER_H
-#define __NOPACITY_IMAGEMAGICKWRAPPER_H
-
-#define X_DISPLAY_MISSING
-
-#include <Magick++.h>
-#include <vdr/osd.h>
-
-using namespace Magick;
-
-class cImageMagickWrapper {
-private:
- void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
-public:
- cImageMagickWrapper();
- ~cImageMagickWrapper();
-protected:
- Image buffer;
- Color Argb2Color(tColor col);
- cImage *CreateImage(int width, int height, bool preserveAspect = true);
- cImage CreateImageCopy(void);
- bool LoadImage(std::string FileName, std::string Path, std::string Extension);
- bool LoadImage(const char *fullpath);
- void CreateBackground(tColor back, tColor blend, int width, int height, bool mirror = false);
- void CreateBackgroundReverse(tColor back, tColor blend, int width, int height);
-};
-
-#endif //__NOPACITY_IMAGEMAGICKWRAPPER_H
diff --git a/libcore/imagescaler.c b/libcore/imagescaler.c
deleted file mode 100644
index 64fe3dc..0000000
--- a/libcore/imagescaler.c
+++ /dev/null
@@ -1,149 +0,0 @@
-
-#include "imagescaler.h"
-
-#include <cstdlib>
-#include <cmath>
-
-ImageScaler::ImageScaler() :
- m_memory(NULL),
- m_hor_filters(NULL),
- m_ver_filters(NULL),
- m_buffer(NULL),
- m_dst_image(NULL),
- m_dst_stride(0),
- m_dst_width(0),
- m_dst_height(0),
- m_src_width(0),
- m_src_height(0),
- m_src_x(0),
- m_src_y(0),
- m_dst_x(0),
- m_dst_y(0) {
-}
-
-ImageScaler::~ImageScaler() {
- if ( m_memory ) free( m_memory );
-}
-
-// sin(x)/(x)
-static float sincf( float x ) {
- if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x; // taylor series approximation to avoid 0/0
- return sin(x)/x;
-}
-
-static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) {
- const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size);
-
- for (int i = 0; i < dst_size; i++) {
- const int d = 2*dst_size; // sample position denominator
- const int e = (2*i+1) * src_size - dst_size; // sample position enumerator
- int offset = e / d; // truncated sample position
- const float sub_offset = ((float) (e - offset*d)) / ((float) d); // exact sample position is (float) e/d = offset + sub_offset
-
- // calculate filter coefficients
- float h[4];
- for (int j=0; j<4; j++) {
- const float t = 3.14159265359f * (sub_offset+(1-j));
- h[j] = sincf( fc * t ) * cosf( 0.25f * t ); // sinc-lowpass and cos-window
- }
-
- // ensure that filter does not reach out off image bounds:
- while ( offset < 1 ) {
- h[0] += h[1];
- h[1] = h[2];
- h[2] = h[3];
- h[3] = 0.0f;
- offset++;
- }
-
- while ( offset+3 > src_size ) {
- h[3] += h[2];
- h[2] = h[1];
- h[1] = h[0];
- h[0] = 0.0f;
- offset--;
- }
-
- // coefficients are normalized to sum up to 2048
- const float norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] );
-
- offset--; // offset of fist used pixel
-
- filters[i].m_offset = offset + 4; // store offset of first unused pixel
-
- for (int j=0; j<4; j++) {
- const float t = norm * h[j];
- filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ? (t+0.5f) : (t-0.5f)); // consider ring buffer index permutations
- }
- }
-
- // set end marker
- filters[dst_size].m_offset = (unsigned) -1;
-
-}
-
-void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) {
- m_src_x = 0;
- m_src_y = 0;
- m_dst_x = 0;
- m_dst_y = 0;
-
- m_dst_image = dst_image;
- m_dst_stride = dst_stride;
-
- // if image dimensions do not change we can keep the old filter coefficients
- if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return;
-
- m_dst_width = dst_width;
- m_dst_height = dst_height;
- m_src_width = src_width;
- m_src_height = src_height;
-
- if ( m_memory ) free( m_memory );
-
- const unsigned hor_filters_size = (m_dst_width + 1) * sizeof(Filter); // reserve one extra position for end marker
- const unsigned ver_filters_size = (m_dst_height + 1) * sizeof(Filter);
- const unsigned buffer_size = 4 * m_dst_width * sizeof(TmpPixel);
-
- char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size );
-
- m_memory = p;
-
- m_hor_filters = (Filter *) p; p += hor_filters_size;
- m_ver_filters = (Filter *) p; p += ver_filters_size;
- m_buffer = (TmpPixel *) p;
-
- CalculateFilters( m_hor_filters, m_dst_width , m_src_width );
- CalculateFilters( m_ver_filters, m_dst_height, m_src_height );
-}
-
-// shift range to 0..255 and clamp overflows
-static unsigned shift_clamp( int x ) {
- x = ( x + (1<<21) ) >> 22;
- if ( x < 0 ) return 0;
- if ( x > 255 ) return 255;
- return x;
-}
-
-void ImageScaler::NextSourceLine() {
- m_dst_x = 0;
- m_src_x = 0;
- m_src_y++;
-
- while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) {
- const int h0 = m_ver_filters[m_dst_y].m_coeff[0];
- const int h1 = m_ver_filters[m_dst_y].m_coeff[1];
- const int h2 = m_ver_filters[m_dst_y].m_coeff[2];
- const int h3 = m_ver_filters[m_dst_y].m_coeff[3];
- const TmpPixel *src = m_buffer;
- unsigned *dst = m_dst_image + m_dst_stride * m_dst_y;
-
- for (unsigned i=0; i<m_dst_width; i++) {
- const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 );
- src += 4;
- dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24);
- }
-
- m_dst_y++;
- }
-}
diff --git a/libcore/imagescaler.h b/libcore/imagescaler.h
deleted file mode 100644
index 1182811..0000000
--- a/libcore/imagescaler.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef _ImageScaler_h
-#define _ImageScaler_h
-
-/*!
- * this class scales images consisting of 4 components (RGBA)
- * to an arbitrary size using a 4-tap filter
- */
-class ImageScaler {
-public:
-
- struct Filter {
- unsigned m_offset;
- short m_coeff[4];
- };
-
- ImageScaler();
- ~ImageScaler();
-
- //! set destination image and source image size
- void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );
-
- /*! process one pixel of source image; destination image is written while input is processed
- * SetImageParameters() must be called first
- */
- void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
- m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );
-
- TmpPixel *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
- const Filter *fh;
-
- while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
- *bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
- m_dst_x++;
- bp += 4;
- }
-
- if ( m_src_x == m_src_width ) NextSourceLine();
- }
-
-private:
-
- //! temporary image pixel class - a 4-element integer vector
- class TmpPixel {
- public:
- TmpPixel() {
- }
-
- TmpPixel( int c0, int c1, int c2, int c3 ) {
- Set(c0,c1,c2,c3);
- }
-
- void Set( int c0, int c1, int c2, int c3 ) {
- m_comp[0] = c0;
- m_comp[1] = c1;
- m_comp[2] = c2;
- m_comp[3] = c3;
- }
-
- TmpPixel operator*( int s ) const {
- return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
- }
-
- TmpPixel operator+( const TmpPixel &x ) const {
- return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
- }
-
- // return component i=[0..3] - No range check!
- int operator[](unsigned i) const {
- return m_comp[i];
- }
-
- private:
- int m_comp[4];
- };
-
- //! this is called whenever one input line is processed completely
- void NextSourceLine();
-
- TmpPixel m_hbuf[4]; //! ring buffer for 4 input pixels
- char *m_memory; //! buffer container
- Filter *m_hor_filters; //! buffer for horizontal filters (one for each output image column)
- Filter *m_ver_filters; //! buffer for vertical filters (one for each output image row)
- TmpPixel *m_buffer; //! buffer contains 4 horizontally filtered input lines, multiplexed
- unsigned *m_dst_image; //! pointer to destination image
- unsigned m_dst_stride; //! destination image stride
- unsigned m_dst_width; //! destination image width
- unsigned m_dst_height; //! destination image height
- unsigned m_src_width; //! source image width
- unsigned m_src_height; //! source image height
- unsigned m_src_x; //! x position of next source image pixel
- unsigned m_src_y; //! y position of source image line currently beeing processed
- unsigned m_dst_x; //! x position of next destination image pixel
- unsigned m_dst_y; //! x position of next destination image line
-};
-
-#endif // _ImageScaler_h
-