blob: f0926ec90dc4e3d4a031ccca14fc766526ed88a5 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "splashscreen_impl.h"
27
28#include "../libpng/png.h"
29
30#include <setjmp.h>
31
32#define SIG_BYTES 8
33
34void PNGAPI
35my_png_read_stream(png_structp png_ptr, png_bytep data, png_size_t length)
36{
37 png_uint_32 check;
38
39 SplashStream * stream = (SplashStream*)png_ptr->io_ptr;
40 check = stream->read(stream, data, length);
41 if (check != length)
42 png_error(png_ptr, "Read Error");
43}
44
45int
46SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
47{
48 int stride;
49 ImageFormat srcFormat;
50 png_uint_32 i, rowbytes;
51 png_bytepp row_pointers = NULL;
52 png_bytep image_data = NULL;
53 int success = 0;
54 double gamma;
55
56 png_structp png_ptr = NULL;
57 png_infop info_ptr = NULL;
58
59 png_uint_32 width, height;
60 int bit_depth, color_type;
61
62 ImageRect srcRect, dstRect;
63
64 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
65 if (!png_ptr) {
66 goto done;
67 }
68
69 info_ptr = png_create_info_struct(png_ptr);
70 if (!info_ptr) {
71 goto done;
72 }
73
74 if (setjmp(png_ptr->jmpbuf)) {
75 goto done;
76 }
77
78 png_ptr->io_ptr = io_ptr;
79 png_ptr->read_data_fn = read_func;
80
81 png_set_sig_bytes(png_ptr, SIG_BYTES); /* we already read the 8 signature bytes */
82
83 png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
84
85 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
86 NULL, NULL, NULL);
87
88 /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
89 * transparency chunks to full alpha channel; strip 16-bit-per-sample
90 * images to 8 bits per sample; and convert grayscale to RGB[A]
91 * this may be sub-optimal but this simplifies implementation */
92
93 png_set_expand(png_ptr);
94 png_set_tRNS_to_alpha(png_ptr);
95 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
96 png_set_strip_16(png_ptr);
97 png_set_gray_to_rgb(png_ptr);
98
99 if (png_get_gAMA(png_ptr, info_ptr, &gamma))
100 png_set_gamma(png_ptr, 2.2, gamma);
101
102 png_read_update_info(png_ptr, info_ptr);
103
104 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
105
106 if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
107 goto done;
108 }
109 if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
110 == NULL) {
111 goto done;
112 }
113
114 for (i = 0; i < height; ++i)
115 row_pointers[i] = image_data + i * rowbytes;
116
117 png_read_image(png_ptr, row_pointers);
118
119 SplashCleanup(splash);
120
121 splash->width = width;
122 splash->height = height;
123
124 stride = splash->width * splash->imageFormat.depthBytes;
125
126 splash->frameCount = 1;
127 splash->frames = (SplashImage *)
128 malloc(sizeof(SplashImage) * splash->frameCount);
129 splash->loopCount = 1;
130 splash->frames[0].bitmapBits = malloc(stride * splash->height);
131 splash->frames[0].delay = 0;
132
133 /* FIXME: sort out the real format */
134 initFormat(&srcFormat, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
135 srcFormat.byteOrder = BYTE_ORDER_MSBFIRST;
136
137 initRect(&srcRect, 0, 0, width, height, 1, rowbytes,
138 image_data, &srcFormat);
139 initRect(&dstRect, 0, 0, width, height, 1, stride,
140 splash->frames[0].bitmapBits, &splash->imageFormat);
141 convertRect(&srcRect, &dstRect, CVT_COPY);
142
143 SplashInitFrameShape(splash, 0);
144
145 png_read_end(png_ptr, NULL);
146 success = 1;
147
148 done:
149 free(row_pointers);
150 free(image_data);
151 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
152 return success;
153}
154
155int
156SplashDecodePngStream(Splash * splash, SplashStream * stream)
157{
158 unsigned char sig[SIG_BYTES];
159 int success = 0;
160
161 stream->read(stream, sig, SIG_BYTES);
162 if (!png_check_sig(sig, SIG_BYTES)) {
163 goto done;
164 }
165 success = SplashDecodePng(splash, my_png_read_stream, stream);
166
167 done:
168 return success;
169}