summaryrefslogtreecommitdiff
path: root/libcore
diff options
context:
space:
mode:
authorManuel Reimer <manuel.reimer@gmx.de>2014-11-02 13:41:21 +0100
committerManuel Reimer <manuel.reimer@gmx.de>2014-11-02 13:41:21 +0100
commite07e56a3faced2f2ef7459cc13c2bda6f65f68ba (patch)
tree96cf997be6080a53aa65ca0d5c551dab9d10c702 /libcore
parent052bc504085a4be9fed4dfc54ab8af8a011e6984 (diff)
downloadvdr-plugin-skindesigner-e07e56a3faced2f2ef7459cc13c2bda6f65f68ba.tar.gz
vdr-plugin-skindesigner-e07e56a3faced2f2ef7459cc13c2bda6f65f68ba.tar.bz2
Added JPEG support
Diffstat (limited to 'libcore')
-rw-r--r--libcore/imageloader.c137
-rw-r--r--libcore/imageloader.h51
2 files changed, 185 insertions, 3 deletions
diff --git a/libcore/imageloader.c b/libcore/imageloader.c
index bb88b70..527e5d6 100644
--- a/libcore/imageloader.c
+++ b/libcore/imageloader.c
@@ -1,7 +1,6 @@
#include "../config.h"
#include "helpers.h"
#include "imageloader.h"
-//#include <math.h>
#include <string>
#include <dirent.h>
#include <iostream>
@@ -69,6 +68,8 @@ bool cImageLoader::LoadImage(const char *fullpath) {
importer = new cImageImporterPNG;
else if (endswith(fullpath, ".svg"))
importer = new cImageImporterSVG;
+ else if (endswith(fullpath, ".jpg"))
+ importer = new cImageImporterJPG;
else
return false;
@@ -209,3 +210,137 @@ void cImageImporterSVG::GetImageSize(int &width, int &height) {
height = dim.height;
}
}
+
+//
+// Image importer for JPG
+//
+
+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;
+ }
+
+ // We set up the normal JPEG error routines, then override error_exit.
+ struct my_error_mgr jerr;
+ cinfo = (j_decompress_ptr)malloc(sizeof(struct jpeg_decompress_struct));
+ 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
+ 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_EXT_ARGB;
+
+ // Step 5: Start decompressor
+ (void) jpeg_start_decompress(cinfo);
+
+ // Bytes per row in output buffer
+ int row_stride = cinfo->output_width * cinfo->output_components;
+
+ // Allocate buffer
+ unsigned long bmp_size = row_stride * cinfo->output_height;
+ bmp_buffer = (unsigned char*)malloc(bmp_size);
+
+ // Step 6: while (scan lines remain to be read)
+ while (cinfo->output_scanline < cinfo->output_height) {
+ unsigned char *buffer_array[1];
+ buffer_array[0] = bmp_buffer + (cinfo->output_scanline) * row_stride;
+ jpeg_read_scanlines(cinfo, buffer_array, 1);
+ }
+
+ // Step 7: Finish decompression
+ (void)jpeg_finish_decompress(cinfo);
+ fclose(infile);
+
+ // --> At this point we have raw RGB data in bmp_buffer
+
+ // Create new Cairo surface from our raw image data
+ cairo_surface_t *surface;
+ surface = cairo_image_surface_create_for_data(bmp_buffer,
+ CAIRO_FORMAT_ARGB32,
+ cinfo->output_width,
+ cinfo->output_height,
+ row_stride);
+
+ // Draw surface to Cairo
+ if (surface) {
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_paint(cr);
+ cairo_surface_destroy(surface);
+ }
+
+ // 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.
+ free(bmp_buffer);
+ jpeg_destroy_decompress(cinfo);
+ free(cinfo);
+ cinfo = NULL;
+}
+
+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 6caf19f..e90f459 100644
--- a/libcore/imageloader.h
+++ b/libcore/imageloader.h
@@ -1,10 +1,10 @@
#ifndef __NOPACITY_IMAGELOADER_H
#define __NOPACITY_IMAGELOADER_H
-#define X_DISPLAY_MISSING
-
#include <cairo.h>
#include <librsvg/rsvg.h>
+#include <jpeglib.h>
+#include <setjmp.h>
#include <vdr/osd.h>
#include <vdr/tools.h>
@@ -44,6 +44,53 @@ private:
RsvgHandle *handle;
};
+// Image importer for JPG
+
+#if BITS_IN_JSAMPLE != 8
+ #error libjpeg-turbo has to be compiled with 8-bit samples!
+#endif
+#ifndef JCS_EXTENSIONS
+ #error libjpeg-turbo with JCS_EXTENSIONS required!
+#endif
+
+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.
+ // We could postpone this until after returning, if we chose.
+ (*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);
+ dsyslog("skindesigner: libjpeg error: %s", buf);
+}
+
+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;
+};
+
+
class cImageLoader {
private: