diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-04-03 13:11:55 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-04-03 13:11:55 +1000 |
commit | a83758e5ab818c6f144f8b7e39f367bb122fd56b (patch) | |
tree | ab75b20eed13db1a95310707f7c40da7af0769a0 /libtwin | |
parent | c485ccb40d72cf3ec286af30a66ae68632ed572c (diff) |
Add simple jpeg loader based on libjpeg
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'libtwin')
-rw-r--r-- | libtwin/twin_jpeg.c | 170 | ||||
-rw-r--r-- | libtwin/twin_jpeg.h | 28 |
2 files changed, 198 insertions, 0 deletions
diff --git a/libtwin/twin_jpeg.c b/libtwin/twin_jpeg.c new file mode 100644 index 0000000..48574e8 --- /dev/null +++ b/libtwin/twin_jpeg.c @@ -0,0 +1,170 @@ +/* + * libjpeg interface to twin + * + * Copyright 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * + * This Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Twin Library; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <setjmp.h> +#include <jpeglib.h> + +#include "twin_jpeg.h" + + +#if BITS_IN_JSAMPLE != 8 +#error supports only libjpeg with 8 bits per sample +#endif + +#if 1 +#define DEBUG(fmt...) printf(fmt) +#else +#define DEBUG(fmt...) +#endif + +struct twin_jpeg_err_mgr { + struct jpeg_error_mgr mgr; + jmp_buf jbuf; +}; + +static void twin_jpeg_error_exit(j_common_ptr cinfo) +{ + struct twin_jpeg_err_mgr *jerr = + (struct twin_jpeg_err_mgr *)cinfo->err; + + /* Do we want to display crap ? Maybe make that an option... */ + (*cinfo->err->output_message)(cinfo); + + longjmp(jerr->jbuf, 1); +} + + +twin_pixmap_t *twin_jpeg_to_pixmap(const char *filepath, twin_format_t fmt) +{ + struct jpeg_decompress_struct cinfo; + struct twin_jpeg_err_mgr jerr; + FILE *infile; + JSAMPARRAY rowbuf; + int rowstride; + twin_pixmap_t *pix = NULL; + twin_coord_t width, height; + + /* Current implementation only produces TWIN_ARGB32 + * and TWIN_A8 + */ + if (fmt != TWIN_ARGB32 && fmt != TWIN_A8) + return NULL; + + /* Open file first, as example */ + infile = fopen(filepath, "rb"); + if (infile == NULL) { + fprintf(stderr, "can't open %s\n", filepath); + return NULL; + } + + /* Error handling crap */ + memset(&cinfo, 0, sizeof(cinfo)); + cinfo.err = jpeg_std_error(&jerr.mgr); + jerr.mgr.error_exit = twin_jpeg_error_exit; + if (setjmp(jerr.jbuf)) { + fprintf(stderr, "failure decoding %s\n", filepath); + if (pix) + twin_pixmap_destroy(pix); + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return NULL; + } + + /* Init libjpeg, hook it up to file and read header */ + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile); + (void)jpeg_read_header(&cinfo, TRUE); + + /* Settings */ + width = cinfo.image_width; + height = cinfo.image_height; + if (fmt == TWIN_ARGB32) + cinfo.out_color_space = JCS_RGB; + else + cinfo.out_color_space = JCS_GRAYSCALE; + DEBUG("cinfo.image_width = %d\n", cinfo.image_width); + DEBUG("cinfo.image_height = %d\n", cinfo.image_height); + + /* Allocate pixmap */ + pix = twin_pixmap_create(fmt, width, height); + if (pix == NULL) + longjmp(jerr.jbuf, 1); + + /* Start decompression engine */ + (void)jpeg_start_decompress(&cinfo); + + DEBUG("cinfo.output_width = %d\n", cinfo.output_width); + DEBUG("cinfo.output_height = %d\n", cinfo.output_height); + DEBUG("cinfo.output_components = %d\n", cinfo.output_components); + DEBUG("cinfo.output_color_comp = %d\n", cinfo.out_color_components); + DEBUG("cinfo.rec_outbuf_height = %d\n", cinfo.rec_outbuf_height); + DEBUG("cinfo.out_color_space = %d\n", cinfo.out_color_space); + + if ((fmt == TWIN_A8 && cinfo.output_components != 1) || + (fmt == TWIN_ARGB32 && (cinfo.output_components != 3 && + cinfo.output_components != 4))) + longjmp(jerr.jbuf, 1); + + rowstride = cinfo.output_width * cinfo.output_components; + DEBUG("rowstride = %d\n", rowstride); + + rowbuf = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, rowstride, 1); + + /* Process rows */ + while (cinfo.output_scanline < cinfo.output_height) { + twin_pointer_t p = + twin_pixmap_pointer(pix, 0, cinfo.output_scanline); + (void)jpeg_read_scanlines(&cinfo, rowbuf, 1); + if (fmt == TWIN_A8 || cinfo.output_components == 4) + memcpy(p.a8, rowbuf, rowstride); + else { + JSAMPLE *s = *rowbuf; + unsigned int i; + + for (i = 0; i < width; i++) { + unsigned int r, g, b; + r = *(s++); + g = *(s++); + b = *(s++); + *(p.argb32++) = 0xff000000u | + (r << 16) | (g << 8) | b; + } + } + } + + /* Cleanup */ + (void)jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + fclose(infile); + + return pix; +} + diff --git a/libtwin/twin_jpeg.h b/libtwin/twin_jpeg.h new file mode 100644 index 0000000..828e361 --- /dev/null +++ b/libtwin/twin_jpeg.h @@ -0,0 +1,28 @@ +/* + * Libjpeg interface to twin + * + * Copyright 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * + * This Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Twin Library; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _TWIN_JPEG_H_ +#define _TWIN_JPEG_H_ + +#include <libtwin/twin.h> + +twin_pixmap_t *twin_jpeg_to_pixmap(const char *filepath, twin_format_t fmt); + +#endif /* _TWIN_JPEG_H_ */ |