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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "../config.h"
32 #include "../wrlib/wraster.h"
37 struct jpeg_error_mgr pub
; /* "public" fields */
39 jmp_buf setjmp_buffer
; /* for return to caller */
42 typedef struct my_error_mgr
*my_error_ptr
;
45 * Here's the routine that will replace the standard error_exit method:
48 static void my_error_exit(j_common_ptr cinfo
)
50 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
51 my_error_ptr myerr
= (my_error_ptr
) cinfo
->err
;
53 /* Always display the message. */
54 /* We could postpone this until after returning, if we chose. */
55 (*cinfo
->err
->output_message
) (cinfo
);
57 /* Return control to the setjmp point */
58 longjmp(myerr
->setjmp_buffer
, 1);
61 static Bool
canLoad(RContext
* rc
)
63 if (rc
->depth
!= 16 || rc
->vclass
!= TrueColor
64 || rc
->red_offset
!= 11 || rc
->green_offset
!= 5 || rc
->blue_offset
!= 0)
70 static void readData(RContext
* rc
, struct jpeg_decompress_struct
*cinfo
, JSAMPROW
* buffer
, RXImage
* ximg
)
77 while (cinfo
->output_scanline
< cinfo
->output_height
) {
79 jpeg_read_scanlines(cinfo
, buffer
, (JDIMENSION
) 1);
81 if (cinfo
->out_color_space
== JCS_RGB
) {
82 for (i
= 0, j
= 0; i
< cinfo
->image_width
; i
++) {
85 (((unsigned long)buffer
[0][j
]) & 0xf8) << 8,
86 (((unsigned long)buffer
[0][j
+ 1]) & 0xf4) << 3,
87 (((unsigned long)buffer
[0][j
+ 2])) >> 3);
89 pixel
= (((unsigned long)buffer
[0][j
++]) & 0xf8) << 8
90 | (((unsigned long)buffer
[0][j
++]) & 0xf4) << 3
91 | (((unsigned long)buffer
[0][j
++])) >> 3;
93 XPutPixel(ximg
->image
, i
, y
, pixel
);
96 for (i
= 0, j
= 0; i
< cinfo
->image_width
; i
++, j
++) {
98 pixel
= (unsigned long)buffer
[0][j
] << 8
99 | (unsigned long)buffer
[0][j
] << 3 | (unsigned long)buffer
[0][j
] >> 3;
101 XPutPixel(ximg
->image
, i
, y
, pixel
);
108 Pixmap
LoadJPEG(RContext
* rc
, char *file_name
, int *width
, int *height
)
110 struct jpeg_decompress_struct cinfo
;
113 struct my_error_mgr jerr
;
114 RXImage
*ximg
= NULL
;
115 unsigned char buf
[8];
121 file
= fopen(file_name
, "rb");
125 if (fread(buf
, 2, 1, file
) != 1) {
129 if (buf
[0] != 0xff || buf
[1] != 0xd8) {
135 cinfo
.err
= jpeg_std_error(&jerr
.pub
);
136 jerr
.pub
.error_exit
= my_error_exit
;
137 /* Establish the setjmp return context for my_error_exit to use. */
138 if (setjmp(jerr
.setjmp_buffer
)) {
139 /* If we get here, the JPEG code has signaled an error.
140 * We need to clean up the JPEG object, close the input file, and return.
142 jpeg_destroy_decompress(&cinfo
);
146 RDestroyXImage(rc
, ximg
);
152 jpeg_create_decompress(&cinfo
);
154 jpeg_stdio_src(&cinfo
, file
);
156 jpeg_read_header(&cinfo
, TRUE
);
158 buffer
[0] = (JSAMPROW
) malloc(cinfo
.image_width
* cinfo
.num_components
);
160 RErrorCode
= RERR_NOMEMORY
;
164 if (cinfo
.jpeg_color_space
== JCS_GRAYSCALE
) {
165 cinfo
.out_color_space
= JCS_GRAYSCALE
;
167 cinfo
.out_color_space
= JCS_RGB
;
168 cinfo
.quantize_colors
= FALSE
;
169 cinfo
.do_fancy_upsampling
= FALSE
;
170 cinfo
.do_block_smoothing
= FALSE
;
171 jpeg_calc_output_dimensions(&cinfo
);
173 ximg
= RCreateXImage(rc
, rc
->depth
, cinfo
.image_width
, cinfo
.image_height
);
177 jpeg_start_decompress(&cinfo
);
179 readData(rc
, &cinfo
, buffer
, ximg
);
181 jpeg_finish_decompress(&cinfo
);
183 p
= XCreatePixmap(rc
->dpy
, rc
->drawable
, cinfo
.image_width
, cinfo
.image_height
, rc
->depth
);
185 RPutXImage(rc
, p
, rc
->copy_gc
, ximg
, 0, 0, 0, 0, cinfo
.image_width
, cinfo
.image_height
);
187 *width
= cinfo
.image_width
;
188 *height
= cinfo
.image_height
;
191 jpeg_destroy_decompress(&cinfo
);
199 RDestroyXImage(rc
, ximg
);
204 #endif /* USE_JPEG */