2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
20 #include "base_config.h"
21 #include "base_image.h"
23 /*---------------------------------------------------------------------------*/
25 void image_size(int *W, int *H, int w, int h)
27 /* Round the image size up to the next power-of-two. */
32 while (*W < w) *W *= 2;
33 while (*H < h) *H *= 2;
36 /*---------------------------------------------------------------------------*/
38 static void *image_load_png(const char *filename, int *width,
44 png_structp readp = NULL;
45 png_infop infop = NULL;
46 png_bytep *bytep = NULL;
47 unsigned char *p = NULL;
49 /* Initialize all PNG import data structures. */
51 if (!(fp = fopen(filename, FMODE_RB)))
54 if (!(readp = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)))
57 if (!(infop = png_create_info_struct(readp)))
60 /* Enable the default PNG error handler. */
62 if (setjmp(png_jmpbuf(readp)) == 0)
66 /* Read the PNG header. */
68 png_init_io(readp, fp);
69 png_read_png(readp, infop,
70 PNG_TRANSFORM_EXPAND |
71 PNG_TRANSFORM_STRIP_16 |
72 PNG_TRANSFORM_PACKING, NULL);
74 /* Extract and check image properties. */
76 w = (int) png_get_image_width (readp, infop);
77 h = (int) png_get_image_height(readp, infop);
79 switch (png_get_color_type(readp, infop))
81 case PNG_COLOR_TYPE_GRAY: b = 1; break;
82 case PNG_COLOR_TYPE_GRAY_ALPHA: b = 2; break;
83 case PNG_COLOR_TYPE_RGB: b = 3; break;
84 case PNG_COLOR_TYPE_RGB_ALPHA: b = 4; break;
86 default: longjmp(png_jmpbuf(readp), -1);
89 /* Read the pixel data. */
91 if (!(bytep = png_get_rows(readp, infop)))
92 longjmp(png_jmpbuf(readp), -1);
94 /* Allocate the final pixel buffer and copy pixels there. */
96 if ((p = (unsigned char *) malloc(w * h * b)))
98 for (r = 0; r < h; r++)
99 for (c = 0; c < w; c++)
100 for (i = 0; i < b; i++)
101 p[r*w*b+c*b+i] = (unsigned char) bytep[r][c*b+i];
103 if (width) *width = w;
104 if (height) *height = h;
105 if (bytes) *bytes = b;
110 /* Free all resources. */
112 png_destroy_read_struct(&readp, &infop, NULL);
118 static void *image_load_jpg(const char *filename, int *width,
125 if ((fp = fopen(filename, FMODE_RB)))
127 struct jpeg_decompress_struct cinfo;
128 struct jpeg_error_mgr jerr;
132 /* Initialize the JPG decompressor. */
134 cinfo.err = jpeg_std_error(&jerr);
135 jpeg_create_decompress(&cinfo);
136 jpeg_stdio_src(&cinfo, fp);
138 /* Grab the JPG header info. */
140 jpeg_read_header(&cinfo, TRUE);
141 jpeg_start_decompress(&cinfo);
143 w = cinfo.output_width;
144 h = cinfo.output_height;
145 b = cinfo.output_components;
147 /* Allocate the final pixel buffer and copy pixels there. */
149 if ((p = (GLubyte *) malloc (w * h * b)))
151 while (cinfo.output_scanline < cinfo.output_height)
153 GLubyte *buffer = p + w * b * i;
154 i += jpeg_read_scanlines(&cinfo, &buffer, 1);
157 if (width) *width = w;
158 if (height) *height = h;
159 if (bytes) *bytes = b;
162 jpeg_finish_decompress(&cinfo);
163 jpeg_destroy_decompress(&cinfo);
171 void *image_load(const char *filename, int *width,
175 const char *ext = filename + strlen(filename) - 4;
177 if (strcmp(ext, ".png") == 0 || strcmp(ext, ".PNG") == 0)
178 return image_load_png(filename, width, height, bytes);
179 else if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".JPG") == 0)
180 return image_load_jpg(filename, width, height, bytes);
185 /*---------------------------------------------------------------------------*/
188 * Allocate and return a power-of-two image buffer with the given pixel buffer
189 * centered within in.
191 void *image_next2(const void *p, int w, int h, int b, int *w2, int *h2)
193 unsigned char *src = (unsigned char *) p;
194 unsigned char *dst = NULL;
199 image_size(&W, &H, w, h);
201 if ((dst = (unsigned char *) calloc(W * H * b, sizeof (unsigned char))))
203 int r, dr = (H - h) / 2;
204 int c, dc = (W - w) / 2;
207 for (r = 0; r < h; ++r)
208 for (c = 0; c < w; ++c)
209 for (i = 0; i < b; ++i)
214 dst[(R * W + C) * b + i] = src[(r * w + c) * b + i];
225 * Allocate and return a new down-sampled image buffer.
227 void *image_scale(const void *p, int w, int h, int b, int *wn, int *hn, int n)
229 unsigned char *src = (unsigned char *) p;
230 unsigned char *dst = NULL;
235 if ((dst = (unsigned char *) calloc(W * H * b, sizeof (unsigned char))))
241 /* Iterate each component of each destination pixel. */
243 for (di = 0; di < H; di++)
244 for (dj = 0; dj < W; dj++)
245 for (i = 0; i < b; i++)
249 /* Average the NxN source pixel block for each. */
251 for (si = di * n; si < (di + 1) * n; si++)
252 for (sj = dj * n; sj < (dj + 1) * n; sj++)
253 c += src[(si * w + sj) * b + i];
255 dst[(di * W + dj) * b + i] =
256 (unsigned char) (c / (n * n));
267 * Whiten the RGB channels of the given image without touching any alpha.
269 void image_white(void *p, int w, int h, int b)
271 unsigned char *s = (unsigned char *) p;
276 for (r = 0; r < h; r++)
277 for (c = 0; c < w; c++)
279 int k = (r * w + c) * b;
291 /*---------------------------------------------------------------------------*/