2 * image.c - Functions to load & unpack PNGs and JPEGs
4 * Copyright (C) 2004-2005, Michal Januszewski <spock@gentoo.org>
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License v2. See the file COPYING in the main directory of this archive for
35 #define PALETTE_COLORS 240
36 static int load_png(stheme_t
*theme
, char *filename
, u8
**data
, struct fb_cmap
*cmap
, unsigned int *width
, unsigned int *height
, u8 want_alpha
)
40 png_bytep row_pointer
;
42 int rowbytes
, num_palette
;
43 int i
, j
, bytespp
= fbd
.bytespp
;
50 FILE *fp
= fopen(filename
,"r");
54 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
55 info_ptr
= png_create_info_struct(png_ptr
);
57 if (setjmp(png_jmpbuf(png_ptr
))) {
61 png_init_io(png_ptr
, fp
);
62 png_read_info(png_ptr
, info_ptr
);
64 if (cmap
&& info_ptr
->color_type
!= PNG_COLOR_TYPE_PALETTE
)
67 if (info_ptr
->color_type
== PNG_COLOR_TYPE_GRAY
||
68 info_ptr
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
69 png_set_gray_to_rgb(png_ptr
);
71 if (info_ptr
->bit_depth
== 16)
72 png_set_strip_16(png_ptr
);
74 if (!want_alpha
&& info_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
)
75 png_set_strip_alpha(png_ptr
);
78 if (!(info_ptr
->color_type
& PNG_COLOR_MASK_ALPHA
) & want_alpha
) {
79 png_set_add_alpha(png_ptr
, 0xff, PNG_FILLER_AFTER
);
82 png_read_update_info(png_ptr
, info_ptr
);
84 if (!cmap
&& info_ptr
->color_type
!= PNG_COLOR_TYPE_RGB
&& info_ptr
->color_type
!= PNG_COLOR_TYPE_RGBA
)
88 png_get_PLTE(png_ptr
, info_ptr
, &palette
, &num_palette
);
90 if (num_palette
> cmap
->len
)
94 rowbytes
= png_get_rowbytes(png_ptr
, info_ptr
);
96 if ((width
&& *width
&& info_ptr
->width
!= *width
) || (height
&& *height
&& info_ptr
->height
!= *height
)) {
97 iprint(MSG_ERROR
, "Image size mismatch: %s.\n", filename
);
100 *width
= info_ptr
->width
;
101 *height
= info_ptr
->height
;
104 *data
= malloc(theme
->xres
* theme
->yres
* fbd
.bytespp
);
106 iprint(MSG_CRITICAL
, "Failed to allocate memory for image: %s.\n", filename
);
110 buf
= malloc(rowbytes
);
112 iprint(MSG_CRITICAL
, "Failed to allocate memory for image line buffer.\n");
117 for (i
= 0; i
< info_ptr
->height
; i
++) {
119 row_pointer
= *data
+ info_ptr
->width
* i
;
120 } else if (want_alpha
) {
121 row_pointer
= *data
+ info_ptr
->width
* i
* 4;
126 png_read_row(png_ptr
, row_pointer
, NULL
);
129 int h
= 256 - cmap
->len
;
130 t
= *data
+ info_ptr
->width
* i
;
133 /* Move the colors up by 'h' offset. This is used because fbcon
134 * takes the first 16 colors. */
135 for (j
= 0; j
< rowbytes
; j
++) {
140 /* We only need to convert the image if the alpha channel is not required */
141 } else if (!want_alpha
) {
142 u8
*tmp
= *data
+ info_ptr
->width
* bytespp
* i
;
143 rgba2fb((rgbacolor
*)buf
, tmp
, tmp
, info_ptr
->width
, i
, 0, 0xff);
148 for (i
= 0; i
< cmap
->len
; i
++) {
149 cmap
->red
[i
] = palette
[i
].red
* 257;
150 cmap
->green
[i
] = palette
[i
].green
* 257;
151 cmap
->blue
[i
] = palette
[i
].blue
* 257;
155 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
163 static int is_png(char *filename
)
165 unsigned char header
[8];
166 FILE *fp
= fopen(filename
,"r");
171 fread(header
, 1, 8, fp
);
174 return !png_sig_cmp(header
, 0, 8);
178 static int load_jpeg(char *filename
, u8
**data
, unsigned int *width
, unsigned int *height
)
180 struct jpeg_decompress_struct cinfo
;
181 struct jpeg_error_mgr jerr
;
187 cinfo
.err
= jpeg_std_error(&jerr
);
188 jpeg_create_decompress(&cinfo
);
190 if ((injpeg
= fopen(filename
,"r")) == NULL
) {
191 iprint(MSG_ERROR
, "Can't open file %s!\n", filename
);
195 jpeg_stdio_src(&cinfo
, injpeg
);
196 jpeg_read_header(&cinfo
, TRUE
);
197 jpeg_start_decompress(&cinfo
);
199 if ((width
&& cinfo
.output_width
!= *width
) || (height
&& cinfo
.output_height
!= *height
)) {
200 iprint(MSG_ERROR
, "Image size mismatch: %s.\n", filename
);
203 *width
= cinfo
.output_width
;
204 *height
= cinfo
.output_height
;
207 buf
= malloc(cinfo
.output_width
* cinfo
.output_components
* sizeof(char));
209 iprint(MSG_ERROR
, "Failed to allocate JPEG decompression buffer.\n");
213 *data
= malloc(cinfo
.output_width
* cinfo
.output_height
* fbd
.bytespp
);
215 iprint(MSG_ERROR
, "Failed to allocate memory for image: %s.\n", filename
);
219 for (i
= 0; i
< cinfo
.output_height
; i
++) {
221 jpeg_read_scanlines(&cinfo
, (JSAMPARRAY
) &buf
, 1);
222 tmp
= *data
+ cinfo
.output_width
* fbd
.bytespp
* i
;
223 rgba2fb((rgbacolor
*)buf
, tmp
, tmp
, cinfo
.output_width
, i
, 0, 0xff);
226 jpeg_finish_decompress(&cinfo
);
227 jpeg_destroy_decompress(&cinfo
);
234 static int load_bg_images(stheme_t
*theme
, char mode
)
236 struct fb_image
*img
= (mode
== 'v') ? &theme
->verbose_img
: &theme
->silent_img
;
240 img
->width
= theme
->xres
;
241 img
->height
= theme
->yres
;
242 img
->depth
= fbd
.var
.bits_per_pixel
;
244 /* Deal with 8bpp modes. Only PNGs can be loaded, and pic256
245 * option has to be used to specify the filename of the image */
246 if (fbd
.var
.bits_per_pixel
== 8) {
247 pic
= (mode
== 'v') ? theme
->pic256
: theme
->silentpic256
;
254 iprint(MSG_ERROR
, "Unrecognized format of the verbose 8bpp background image.\n");
258 /* We have a palette of 256 colors, but fbcon takes 16 of these for
259 * font colors in verbose mode, so we have 240 left for the picture */
262 img
->cmap
.start
= 16;
268 img
->cmap
.transp
= NULL
;
269 img
->cmap
.red
= malloc(i
* 3 * 2);
271 if (!img
->cmap
.red
) {
272 iprint(MSG_ERROR
, "Failed to allocate memory for the image palette.\n");
276 img
->cmap
.green
= img
->cmap
.red
+ i
;
277 img
->cmap
.blue
= img
->cmap
.green
+ i
;
280 if (load_png(theme
, pic
, (u8
**)&img
->data
, &img
->cmap
, &img
->width
, &img
->height
, 0)) {
281 iprint(MSG_ERROR
, "Failed to load PNG file %s.\n", pic
);
285 iprint(MSG_WARN
, "This version of splashutils has been compiled without support for 8bpp modes.\n");
288 /* Deal with 15, 16, 24 and 32bpp modes */
290 pic
= (mode
== 'v') ? theme
->pic
: theme
->silentpic
;
297 i
= load_png(theme
, pic
, (u8
**)&img
->data
, NULL
, &img
->width
, &img
->height
, 0);
301 i
= load_jpeg(pic
, (u8
**)&img
->data
, &img
->width
, &img
->height
);
305 iprint(MSG_ERROR
, "Failed to load image %s.\n", pic
);
313 int load_images(stheme_t
*theme
, char mode
)
317 if (load_bg_images(theme
, mode
))
322 for (i
= theme
->icons
.head
; i
!= NULL
; i
= i
->next
) {
323 icon_img
*ii
= (icon_img
*) i
->p
;
326 if (!is_png(ii
->filename
)) {
327 iprint(MSG_ERROR
, "Icon %s is not a PNG file.\n", ii
->filename
);
331 if (load_png(theme
, ii
->filename
, &ii
->picbuf
, NULL
, &ii
->w
, &ii
->h
, 1)) {
332 iprint(MSG_ERROR
, "Failed to load icon %s.\n", ii
->filename
);