TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
img.cpp
Go to the documentation of this file.
1/***************************************************************************
2 img.cpp -- Images manipulation
3 -------------------
4 created : Tue Aug 17 20:13:08 CEST 1999
5 copyright : (C) 1999-2026 by Eric EspiƩ, Bernhard Wymann
6 email : berniw@bluewin.ch
7
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
25
26#ifdef WIN32
27#include <windows.h>
28#endif
29
30#include "png.h"
31
32#include <tgfclient.h>
33#include <stdlib.h>
34#include <stdio.h>
35#ifdef WIN32
36#include <direct.h>
37#endif
38
39#include <portability.h>
40
41#define PNG_BYTES_TO_CHECK 4
42
52unsigned char *
53GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma)
54{
55 unsigned char buf[PNG_BYTES_TO_CHECK];
56 FILE *fp;
57 png_structp png_ptr;
58 png_infop info_ptr;
59 png_uint_32 width, height;
60 int bit_depth, color_type, interlace_type;
61
62 /* png_color_16p image_background; */
63 double gamma;
64 png_bytep *row_pointers;
65 unsigned char *image_ptr, *cur_ptr;
66 png_uint_32 rowbytes;
67 png_uint_32 i;
68
69 if ((fp = fopen(filename, "rb")) == NULL) {
70 GfTrace("Can't open file %s\n", filename);
71 return (unsigned char *)NULL;
72 }
73
74 if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) {
75 GfTrace("Can't read file %s\n", filename);
76 fclose(fp);
77 return (unsigned char *)NULL;
78 }
79
80 if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
81 GfTrace("File %s not in png format\n", filename);
82 fclose(fp);
83 return (unsigned char *)NULL;
84 }
85
86 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
87 if (png_ptr == NULL) {
88 GfTrace("Img Failed to create read_struct\n");
89 fclose(fp);
90 return (unsigned char *)NULL;
91 }
92
93 info_ptr = png_create_info_struct(png_ptr);
94 if (info_ptr == NULL) {
95 fclose(fp);
96 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
97 return (unsigned char *)NULL;
98 }
99
100 if (setjmp(png_jmpbuf(png_ptr)))
101 {
102 /* Free all of the memory associated with the png_ptr and info_ptr */
103 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
104 fclose(fp);
105 /* If we get here, we had a problem reading the file */
106 return (unsigned char *)NULL;
107 }
108
109 png_init_io(png_ptr, fp);
110 png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
111 png_read_info(png_ptr, info_ptr);
112 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
113 *widthp = (int)width;
114 *heightp = (int)height;
115
116 if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) png_set_invert_mono(png_ptr);
117 if (bit_depth == 16) {
118 png_set_swap(png_ptr);
119 png_set_strip_16(png_ptr);
120 }
121
122 if (bit_depth < 8) {
123 png_set_packing(png_ptr);
124 }
125
126 if (color_type == PNG_COLOR_TYPE_PALETTE) {
127 png_set_expand(png_ptr);
128 }
129
130 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
131 png_set_expand(png_ptr);
132 }
133
134 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
135 png_set_expand(png_ptr);
136 }
137
138 if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
139 png_set_gray_to_rgb(png_ptr);
140 }
141
142 if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB) {
143 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
144 }
145
146 if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
147 png_set_gamma(png_ptr, screen_gamma, gamma);
148 } else {
149 png_set_gamma(png_ptr, screen_gamma, 0.50);
150 }
151
152 png_read_update_info(png_ptr, info_ptr);
153 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
154
155 // RGBA expected.
156 if (rowbytes != (4 * width)) {
157 GfTrace("%s bad byte count... %lu instead of %lu\n", filename, (unsigned long) rowbytes, (unsigned long) (4 * width));
158 fclose(fp);
159 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
160 return (unsigned char *)NULL;
161 }
162
163 row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
164 if (row_pointers == NULL) {
165 fclose(fp);
166 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
167 return (unsigned char *)NULL;
168 }
169
170 image_ptr = (unsigned char *)malloc(height * rowbytes);
171 if (image_ptr == NULL) {
172 fclose(fp);
173 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
174 return (unsigned char *)NULL;
175 }
176
177 for (i = 0, cur_ptr = image_ptr + (height - 1) * rowbytes ; i < height; i++, cur_ptr -= rowbytes) {
178 row_pointers[i] = cur_ptr;
179 }
180
181 png_read_image(png_ptr, row_pointers);
182 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
183 free(row_pointers);
184
185 fclose(fp);
186 return image_ptr;
187}
188
189
190static int
191writePng(unsigned char *img, const char *filename, int width, int height, int writeGamma)
192{
193 FILE *fp;
194 png_structp png_ptr;
195 png_infop info_ptr;
196 png_bytep *row_pointers;
197 png_uint_32 rowbytes;
198 int i;
199 unsigned char *cur_ptr;
200
201 fp = fopen(filename, "wb");
202 if (fp == NULL) {
203 GfTrace("Can't open file %s\n", filename);
204 return -1;
205 }
206
207 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
208 if (png_ptr == NULL) {
209 fclose(fp);
210 return -1;
211 }
212
213 info_ptr = png_create_info_struct(png_ptr);
214 if (info_ptr == NULL) {
215 fclose(fp);
216 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
217 return -1;
218 }
219
220 if (setjmp(png_jmpbuf(png_ptr))) {
221 png_destroy_write_struct(&png_ptr, &info_ptr);
222 fclose(fp);
223 return -1;
224 }
225
226 png_init_io(png_ptr, fp);
227 png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
228 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
229 if (writeGamma) {
230#if 0
231 void *handle;
232 float screen_gamma;
233
235 screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
236 GfParmReleaseHandle(handle);
237#else
238 const float screen_gamma = 2.0;
239#endif
240 png_set_gAMA(png_ptr, info_ptr, screen_gamma);
241 }
242 /* png_set_bgr(png_ptr); TO INVERT THE COLORS !!!! */
243 png_write_info(png_ptr, info_ptr);
244 png_write_flush(png_ptr);
245
246 rowbytes = width * 3;
247 row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
248
249 if (row_pointers == NULL) {
250 fclose(fp);
251 png_destroy_write_struct(&png_ptr, &info_ptr);
252 return -1;
253 }
254
255 for (i = 0, cur_ptr = img + (height - 1) * rowbytes ; i < height; i++, cur_ptr -= rowbytes) {
256 row_pointers[i] = cur_ptr;
257 }
258
259 png_write_image(png_ptr, row_pointers);
260 png_write_end(png_ptr, (png_infop)NULL);
261 png_destroy_write_struct(&png_ptr, &info_ptr);
262 fclose(fp);
263 free(row_pointers);
264 return 0;
265}
266
276int
277GfImgWritePng(unsigned char *img, const char *filename, int width, int height)
278{
279 return writePng(img, filename, width, height, 1);
280}
281
291int
292GfImgWritePngNoGamma(unsigned char *img, const char *filename, int width, int height)
293{
294 return writePng(img, filename, width, height, 0);
295}
296
301void
302GfImgFreeTex(GLuint tex)
303{
304 if (tex != 0) {
305 glDeleteTextures(1, &tex);
306 }
307}
308
314GLuint
315GfImgReadTex(char *filename)
316{
317 void *handle;
318 float screen_gamma;
319 GLbyte *tex;
320 int w, h;
321 GLuint retTex;
322 const int BUFSIZE = 1024;
323 char buf[BUFSIZE];
324
325 snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
327 screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
328 tex = (GLbyte*)GfImgReadPng(filename, &w, &h, screen_gamma);
329
330 if (!tex) {
331 GfParmReleaseHandle(handle);
332 return 0;
333 }
334
335 glGenTextures(1, &retTex);
336 glBindTexture(GL_TEXTURE_2D, retTex);
337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
339 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)(tex));
340
341 free(tex);
342
343 GfParmReleaseHandle(handle);
344 return retTex;
345}
int GfImgWritePngNoGamma(unsigned char *img, const char *filename, int width, int height)
Write a framebuffer capture to a png image on disk without gamma metadata.
Definition img.cpp:292
unsigned char * GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma)
Load an image from disk to a buffer in RGBA mode.
Definition img.cpp:53
void GfImgFreeTex(GLuint tex)
Free the texture.
Definition img.cpp:302
GLuint GfImgReadTex(char *filename)
Read a png image into a texture.
Definition img.cpp:315
int GfImgWritePng(unsigned char *img, const char *filename, int width, int height)
Write a buffer to a png image on disk.
Definition img.cpp:277
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition params.cpp:2534
void GfParmReleaseHandle(void *parmHandle)
Release given parameter set handle parmHandle.
Definition params.cpp:1963
void * GfParmReadFile(const char *file, int mode)
Read parameter set from file and return handle to parameter set.
Definition params.cpp:1173
#define PNG_BYTES_TO_CHECK
Definition img.cpp:41
static int writePng(unsigned char *img, const char *filename, int width, int height, int writeGamma)
Definition img.cpp:191
#define GFSCR_CONF_FILE
#define GFSCR_SECT_PROP
#define GFSCR_ATT_GAMMA
char * GetLocalDir(void)
Definition tgf.cpp:230
#define GFPARM_RMODE_CREAT
Allow an empty in-memory set on file-open failure; does not write a file.
Definition tgf.h:266
#define GFPARM_RMODE_STD
Return a new handle sharing cached data for this filename, if available.
Definition tgf.h:264
#define GfTrace
Definition tgf.h:335
The Gaming Framework API (client part).