1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2011 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
25 JPG image support using jpeg library.
39 #include <GP_Context.h>
42 GP_RetCode
GP_OpenJPG(const char *src_path
, FILE **f
)
44 *f
= fopen(src_path
, "rb");
47 GP_DEBUG(1, "Failed to open '%s' : %s",
48 src_path
, strerror(errno
));
52 //TODO: check signature and rewind the stream
58 struct jpeg_error_mgr error_mgr
;
63 static void my_error_exit(j_common_ptr cinfo
)
65 struct my_jpg_err
*my_err
= (struct my_jpg_err
*) cinfo
->err
;
67 GP_DEBUG(1, "ERROR reading jpeg file");
69 longjmp(my_err
->setjmp_buf
, 1);
72 static const char *get_colorspace(J_COLOR_SPACE color_space
)
74 switch (color_space
) {
90 GP_RetCode
GP_ReadJPG(FILE *f
, GP_Context
**res
)
92 struct jpeg_decompress_struct cinfo
;
93 struct my_jpg_err my_err
;
94 GP_Context
*ret
= NULL
;
96 cinfo
.err
= jpeg_std_error(&my_err
.error_mgr
);
97 my_err
.error_mgr
.error_exit
= my_error_exit
;
99 if (setjmp(my_err
.setjmp_buf
)) {
100 jpeg_destroy_decompress(&cinfo
);
106 jpeg_create_decompress(&cinfo
);
107 jpeg_stdio_src(&cinfo
, f
);
109 jpeg_read_header(&cinfo
, TRUE
);
111 GP_DEBUG(1, "Have %s JPEG size %ux%u %i channels",
112 get_colorspace(cinfo
.jpeg_color_space
),
113 cinfo
.image_width
, cinfo
.image_height
,
114 cinfo
.num_components
);
118 switch (cinfo
.out_color_space
) {
120 pixel_type
= GP_PIXEL_G8
;
123 pixel_type
= GP_PIXEL_RGB888
;
126 pixel_type
= GP_PIXEL_UNKNOWN
;
129 if (pixel_type
== GP_PIXEL_UNKNOWN
) {
130 GP_DEBUG(1, "Can't handle %s JPEG output format",
131 get_colorspace(cinfo
.out_color_space
));
132 jpeg_destroy_decompress(&cinfo
);
137 ret
= GP_ContextAlloc(cinfo
.image_width
, cinfo
.image_height
,
141 GP_DEBUG(1, "Malloc failed :(");
142 jpeg_destroy_decompress(&cinfo
);
147 jpeg_start_decompress(&cinfo
);
149 while (cinfo
.output_scanline
< cinfo
.output_height
) {
150 uint32_t y
= cinfo
.output_scanline
;
152 JSAMPROW addr
= (void*)GP_PIXEL_ADDR(ret
, 0, y
);
153 jpeg_read_scanlines(&cinfo
, &addr
, 1);
155 if (pixel_type
!= GP_PIXEL_RGB888
)
158 //TODO: fixme bigendian?
159 /* fix the pixel, as we want in fact BGR */
162 for (i
= 0; i
< ret
->w
; i
++) {
163 uint8_t *pix
= GP_PIXEL_ADDR(ret
, i
, y
);
164 GP_SWAP(pix
[0], pix
[2]);
168 jpeg_finish_decompress(&cinfo
);
169 jpeg_destroy_decompress(&cinfo
);
176 GP_RetCode
GP_LoadJPG(const char *src_path
, GP_Context
**res
)
181 if ((ret
= GP_OpenJPG(src_path
, &f
)))
184 return GP_ReadJPG(f
, res
);