diff options
author | Manuel Reimer <manuel.reimer@gmx.de> | 2014-11-02 13:41:21 +0100 |
---|---|---|
committer | Manuel Reimer <manuel.reimer@gmx.de> | 2014-11-02 13:41:21 +0100 |
commit | e07e56a3faced2f2ef7459cc13c2bda6f65f68ba (patch) | |
tree | 96cf997be6080a53aa65ca0d5c551dab9d10c702 /libcore/imageloader.c | |
parent | 052bc504085a4be9fed4dfc54ab8af8a011e6984 (diff) | |
download | vdr-plugin-skindesigner-e07e56a3faced2f2ef7459cc13c2bda6f65f68ba.tar.gz vdr-plugin-skindesigner-e07e56a3faced2f2ef7459cc13c2bda6f65f68ba.tar.bz2 |
Added JPEG support
Diffstat (limited to 'libcore/imageloader.c')
-rw-r--r-- | libcore/imageloader.c | 137 |
1 files changed, 136 insertions, 1 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; + } +} |