TORCS  1.3.9
The Open Racing Car Simulator
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-2014 by Eric Espie, Bernhard Wymann
6  email : torcs@free.fr
7  version : $Id$
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 
27 #ifdef WIN32
28 #include <windows.h>
29 #endif
30 
31 #include "png.h"
32 
33 #include <tgfclient.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #ifdef WIN32
37 #include <direct.h>
38 #endif
39 
40 #include <portability.h>
41 
42 #define PNG_BYTES_TO_CHECK 4
43 
53 unsigned char *
54 GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma)
55 {
56  unsigned char buf[PNG_BYTES_TO_CHECK];
57  FILE *fp;
58  png_structp png_ptr;
59  png_infop info_ptr;
60  png_uint_32 width, height;
61  int bit_depth, color_type, interlace_type;
62 
63  /* png_color_16p image_background; */
64  double gamma;
65  png_bytep *row_pointers;
66  unsigned char *image_ptr, *cur_ptr;
67  png_uint_32 rowbytes;
68  png_uint_32 i;
69 
70  if ((fp = fopen(filename, "rb")) == NULL) {
71  GfTrace("Can't open file %s\n", filename);
72  return (unsigned char *)NULL;
73  }
74 
75  if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) {
76  GfTrace("Can't read file %s\n", filename);
77  fclose(fp);
78  return (unsigned char *)NULL;
79  }
80 
81  if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
82  GfTrace("File %s not in png format\n", filename);
83  fclose(fp);
84  return (unsigned char *)NULL;
85  }
86 
87  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
88  if (png_ptr == NULL) {
89  GfTrace("Img Failed to create read_struct\n");
90  fclose(fp);
91  return (unsigned char *)NULL;
92  }
93 
94  info_ptr = png_create_info_struct(png_ptr);
95  if (info_ptr == NULL) {
96  fclose(fp);
97  png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
98  return (unsigned char *)NULL;
99  }
100 
101  if (setjmp(png_jmpbuf(png_ptr)))
102  {
103  /* Free all of the memory associated with the png_ptr and info_ptr */
104  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
105  fclose(fp);
106  /* If we get here, we had a problem reading the file */
107  return (unsigned char *)NULL;
108  }
109 
110  png_init_io(png_ptr, fp);
111  png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
112  png_read_info(png_ptr, info_ptr);
113  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
114  *widthp = (int)width;
115  *heightp = (int)height;
116 
117  if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) png_set_invert_mono(png_ptr);
118  if (bit_depth == 16) {
119  png_set_swap(png_ptr);
120  png_set_strip_16(png_ptr);
121  }
122 
123  if (bit_depth < 8) {
124  png_set_packing(png_ptr);
125  }
126 
127  if (color_type == PNG_COLOR_TYPE_PALETTE) {
128  png_set_expand(png_ptr);
129  }
130 
131  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
132  png_set_expand(png_ptr);
133  }
134 
135  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
136  png_set_expand(png_ptr);
137  }
138 
139  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
140  png_set_gray_to_rgb(png_ptr);
141  }
142 
143  if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB) {
144  png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
145  }
146 
147  if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
148  png_set_gamma(png_ptr, screen_gamma, gamma);
149  } else {
150  png_set_gamma(png_ptr, screen_gamma, 0.50);
151  }
152 
153  png_read_update_info(png_ptr, info_ptr);
154  rowbytes = png_get_rowbytes(png_ptr, info_ptr);
155 
156  // RGBA expected.
157  if (rowbytes != (4 * width)) {
158  GfTrace("%s bad byte count... %lu instead of %lu\n", filename, (unsigned long) rowbytes, (unsigned long) (4 * width));
159  fclose(fp);
160  png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
161  return (unsigned char *)NULL;
162  }
163 
164  row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
165  if (row_pointers == NULL) {
166  fclose(fp);
167  png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
168  return (unsigned char *)NULL;
169  }
170 
171  image_ptr = (unsigned char *)malloc(height * rowbytes);
172  if (image_ptr == NULL) {
173  fclose(fp);
174  png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
175  return (unsigned char *)NULL;
176  }
177 
178  for (i = 0, cur_ptr = image_ptr + (height - 1) * rowbytes ; i < height; i++, cur_ptr -= rowbytes) {
179  row_pointers[i] = cur_ptr;
180  }
181 
182  png_read_image(png_ptr, row_pointers);
183  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
184  free(row_pointers);
185 
186  fclose(fp);
187  return image_ptr;
188 }
189 
190 
200 int
201 GfImgWritePng(unsigned char *img, const char *filename, int width, int height)
202 {
203  FILE *fp;
204  png_structp png_ptr;
205  png_infop info_ptr;
206  png_bytep *row_pointers;
207  png_uint_32 rowbytes;
208  int i;
209  unsigned char *cur_ptr;
210 #if 0
211  void *handle;
212 #endif
213  float screen_gamma;
214 
215  fp = fopen(filename, "wb");
216  if (fp == NULL) {
217  GfTrace("Can't open file %s\n", filename);
218  return -1;
219  }
220 
221  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
222  if (png_ptr == NULL) {
223  return -1;
224  }
225 
226  info_ptr = png_create_info_struct(png_ptr);
227  if (info_ptr == NULL) {
228  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
229  return -1;
230  }
231 
232  if (setjmp(png_jmpbuf(png_ptr))) {
233  png_destroy_write_struct(&png_ptr, &info_ptr);
234  fclose(fp);
235  return -1;
236  }
237 
238  png_init_io(png_ptr, fp);
239  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
240  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
241 #if 0
243  screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
244  GfParmReleaseHandle(handle);
245 #else
246  screen_gamma = 2.0;
247 #endif
248  png_set_gAMA(png_ptr, info_ptr, screen_gamma);
249  /* png_set_bgr(png_ptr); TO INVERT THE COLORS !!!! */
250  png_write_info(png_ptr, info_ptr);
251  png_write_flush(png_ptr);
252 
253  rowbytes = width * 3;
254  row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
255 
256  if (row_pointers == NULL) {
257  fclose(fp);
258  png_destroy_write_struct(&png_ptr, &info_ptr);
259  return -1;
260  }
261 
262  for (i = 0, cur_ptr = img + (height - 1) * rowbytes ; i < height; i++, cur_ptr -= rowbytes) {
263  row_pointers[i] = cur_ptr;
264  }
265 
266  png_write_image(png_ptr, row_pointers);
267  png_write_end(png_ptr, (png_infop)NULL);
268  png_destroy_write_struct(&png_ptr, &info_ptr);
269  fclose(fp);
270  free(row_pointers);
271  return 0;
272 }
273 
279 void
280 GfImgFreeTex(GLuint tex)
281 {
282  if (tex != 0) {
283  glDeleteTextures(1, &tex);
284  }
285 }
286 
292 GLuint
293 GfImgReadTex(char *filename)
294 {
295  void *handle;
296  float screen_gamma;
297  GLbyte *tex;
298  int w, h;
299  GLuint retTex;
300  const int BUFSIZE = 1024;
301  char buf[BUFSIZE];
302 
303  snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
305  screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
306  tex = (GLbyte*)GfImgReadPng(filename, &w, &h, screen_gamma);
307 
308  if (!tex) {
309  GfParmReleaseHandle(handle);
310  return 0;
311  }
312 
313  glGenTextures(1, &retTex);
314  glBindTexture(GL_TEXTURE_2D, retTex);
315  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
316  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
317  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)(tex));
318 
319  free(tex);
320 
321  GfParmReleaseHandle(handle);
322  return retTex;
323 }
void GfImgFreeTex(GLuint tex)
Free the texture.
Definition: img.cpp:280
#define GFSCR_ATT_GAMMA
void * GfParmReadFile(const char *file, int mode)
Read parameter set from file and return handle to parameter set.
Definition: params.cpp:1157
int GfImgWritePng(unsigned char *img, const char *filename, int width, int height)
Write a buffer to a png image on disk.
Definition: img.cpp:201
GLuint GfImgReadTex(char *filename)
Read a png image into a texture.
Definition: img.cpp:293
#define GFPARM_RMODE_STD
if handle already openned return it
Definition: tgf.h:265
char * GetLocalDir(void)
Definition: tgf.cpp:231
void GfParmReleaseHandle(void *parmHandle)
Release given parameter set handle parmHandle.
Definition: params.cpp:1834
#define GFSCR_CONF_FILE
#define GFSCR_SECT_PROP
The Gaming Framework API (client part).
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:54
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:2392
#define PNG_BYTES_TO_CHECK
Definition: img.cpp:42
#define GfTrace
Definition: tgf.h:336
#define GFPARM_RMODE_CREAT
Create the file if doesn&#39;t exist.
Definition: tgf.h:267