1 /* directjpeg.c- loads a jpeg file directly into a XImage
3 * WindowMaker window manager
5 * Copyright (c) 1999-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 #include "../src/config.h"
33 #include "../wrlib/wraster.h"
38 struct jpeg_error_mgr pub
; /* "public" fields */
40 jmp_buf setjmp_buffer
; /* for return to caller */
43 typedef struct my_error_mgr
*my_error_ptr
;
46 * Here's the routine that will replace the standard error_exit method:
49 static void my_error_exit(j_common_ptr cinfo
)
51 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
52 my_error_ptr myerr
= (my_error_ptr
) cinfo
->err
;
54 /* Always display the message. */
55 /* We could postpone this until after returning, if we chose. */
56 (*cinfo
->err
->output_message
) (cinfo
);
58 /* Return control to the setjmp point */
59 longjmp(myerr
->setjmp_buffer
, 1);
62 static Bool
canLoad(RContext
* rc
)
64 if (rc
->depth
!= 16 || rc
->vclass
!= TrueColor
65 || rc
->red_offset
!= 11 || rc
->green_offset
!= 5 || rc
->blue_offset
!= 0)
71 static void readData(RContext
* rc
, struct jpeg_decompress_struct
*cinfo
, JSAMPROW
* buffer
, RXImage
* ximg
)
78 while (cinfo
->output_scanline
< cinfo
->output_height
) {
80 jpeg_read_scanlines(cinfo
, buffer
, (JDIMENSION
) 1);
82 if (cinfo
->out_color_space
== JCS_RGB
) {
83 for (i
= 0, j
= 0; i
< cinfo
->image_width
; i
++) {
86 (((unsigned long)buffer
[0][j
]) & 0xf8) << 8,
87 (((unsigned long)buffer
[0][j
+ 1]) & 0xf4) << 3,
88 (((unsigned long)buffer
[0][j
+ 2])) >> 3);
90 pixel
= (((unsigned long)buffer
[0][j
++]) & 0xf8) << 8
91 | (((unsigned long)buffer
[0][j
++]) & 0xf4) << 3
92 | (((unsigned long)buffer
[0][j
++])) >> 3;
94 XPutPixel(ximg
->image
, i
, y
, pixel
);
97 for (i
= 0, j
= 0; i
< cinfo
->image_width
; i
++, j
++) {
99 pixel
= (unsigned long)buffer
[0][j
] << 8
100 | (unsigned long)buffer
[0][j
] << 3 | (unsigned long)buffer
[0][j
] >> 3;
102 XPutPixel(ximg
->image
, i
, y
, pixel
);
109 Pixmap
LoadJPEG(RContext
* rc
, char *file_name
, int *width
, int *height
)
111 struct jpeg_decompress_struct cinfo
;
114 struct my_error_mgr jerr
;
115 RXImage
*ximg
= NULL
;
116 unsigned char buf
[8];
122 file
= fopen(file_name
, "rb");
126 if (fread(buf
, 2, 1, file
) != 1) {
130 if (buf
[0] != 0xff || buf
[1] != 0xd8) {
136 cinfo
.err
= jpeg_std_error(&jerr
.pub
);
137 jerr
.pub
.error_exit
= my_error_exit
;
138 /* Establish the setjmp return context for my_error_exit to use. */
139 if (setjmp(jerr
.setjmp_buffer
)) {
140 /* If we get here, the JPEG code has signaled an error.
141 * We need to clean up the JPEG object, close the input file, and return.
143 jpeg_destroy_decompress(&cinfo
);
147 RDestroyXImage(rc
, ximg
);
153 jpeg_create_decompress(&cinfo
);
155 jpeg_stdio_src(&cinfo
, file
);
157 jpeg_read_header(&cinfo
, TRUE
);
159 buffer
[0] = (JSAMPROW
) malloc(cinfo
.image_width
* cinfo
.num_components
);
161 RErrorCode
= RERR_NOMEMORY
;
165 if (cinfo
.jpeg_color_space
== JCS_GRAYSCALE
) {
166 cinfo
.out_color_space
= JCS_GRAYSCALE
;
168 cinfo
.out_color_space
= JCS_RGB
;
169 cinfo
.quantize_colors
= FALSE
;
170 cinfo
.do_fancy_upsampling
= FALSE
;
171 cinfo
.do_block_smoothing
= FALSE
;
172 jpeg_calc_output_dimensions(&cinfo
);
174 ximg
= RCreateXImage(rc
, rc
->depth
, cinfo
.image_width
, cinfo
.image_height
);
178 jpeg_start_decompress(&cinfo
);
180 readData(rc
, &cinfo
, buffer
, ximg
);
182 jpeg_finish_decompress(&cinfo
);
184 p
= XCreatePixmap(rc
->dpy
, rc
->drawable
, cinfo
.image_width
, cinfo
.image_height
, rc
->depth
);
186 RPutXImage(rc
, p
, rc
->copy_gc
, ximg
, 0, 0, 0, 0, cinfo
.image_width
, cinfo
.image_height
);
188 *width
= cinfo
.image_width
;
189 *height
= cinfo
.image_height
;
192 jpeg_destroy_decompress(&cinfo
);
200 RDestroyXImage(rc
, ximg
);
205 #endif /* USE_JPEG */