FS2_Open
Open source remastering of the Freespace 2 engine
pngutils.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <string.h>
3 
4 #include "bmpman/bmpman.h"
5 #include "cfile/cfile.h"
6 #include "globalincs/pstypes.h"
7 #include "graphics/2d.h"
8 #include "palman/palman.h"
9 #include "png.h"
10 #include "pngutils/pngutils.h"
11 
12 CFILE *png_file = NULL;
13 
14 //copy/pasted from libpng
15 void png_scp_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
16 {
17  png_size_t check;
18 
19  if (png_ptr == NULL)
20  return;
21  /* fread() returns 0 on error, so it is OK to store this in a png_size_t
22  * instead of an int, which is what fread() actually returns.
23  */
24  check = (png_size_t)cfread(data, (png_size_t)1, length, png_file);
25  if (check != length)
26  png_error(png_ptr, "Read Error");
27 }
28 
29 // Reads header information from the PNG file into the bitmap pointer
30 //
31 // filename - name of the PNG bitmap file
32 // w - (output) width of the bitmap
33 // h - (output) height of the bitmap
34 // bpp - (output) bits per pixel of the bitmap
35 //
36 // returns - PNG_ERROR_NONE if successful, otherwise error code
37 //
38 int png_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette)
39 {
41  png_infop info_ptr;
42  png_structp png_ptr;
43 
44  png_file = NULL;
45 
46  //mprintf(("png_read_header: %s\n", real_filename));
47 
48  if (img_cfp == NULL) {
49  strcpy_s( filename, real_filename );
50 
51  char *p = strchr( filename, '.' );
52 
53  if ( p )
54  *p = 0;
55 
56  strcat_s( filename, ".png" );
57 
58  png_file = cfopen( filename , "rb" );
59 
60  if ( !png_file ) {
61  return PNG_ERROR_READING;
62  }
63  } else {
64  png_file = img_cfp;
65  }
66 
67  Assert( png_file != NULL );
68 
69  if (png_file == NULL)
70  return PNG_ERROR_READING;
71 
72  /* Create and initialize the png_struct with the desired error handler
73  * functions. If you want to use the default stderr and longjump method,
74  * you can supply NULL for the last three parameters. We also supply the
75  * the compiler header file version, so that we know if the application
76  * was compiled with a compatible version of the library. REQUIRED
77  */
78  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
79 
80  if (png_ptr == NULL)
81  {
82  mprintf(("png_read_header: error creating read struct\n"));
83  cfclose(png_file);
84  return PNG_ERROR_READING;
85  }
86 
87  /* Allocate/initialize the memory for image information. REQUIRED. */
88  info_ptr = png_create_info_struct(png_ptr);
89  if (info_ptr == NULL)
90  {
91  mprintf(("png_read_header: error creating info struct\n"));
92  cfclose(png_file);
93  png_destroy_read_struct(&png_ptr, NULL, NULL);
94  return PNG_ERROR_READING;
95  }
96 
97  if (setjmp(png_jmpbuf(png_ptr)))
98  {
99  mprintf(("png_read_header: something went wrong\n"));
100  /* Free all of the memory associated with the png_ptr and info_ptr */
101  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
102  cfclose(png_file);
103  /* If we get here, we had a problem reading the file */
104  return PNG_ERROR_READING;
105  }
106 
107  png_set_read_fn(png_ptr, &png_file, png_scp_read_data);
108 
109  png_read_info(png_ptr, info_ptr);
110 
111  if (w) *w = png_get_image_width(png_ptr, info_ptr);
112  if (h) *h = png_get_image_height(png_ptr, info_ptr);
113  // this turns out to be near useless, but meh
114  if (bpp) *bpp = (png_get_channels(png_ptr, info_ptr) * png_get_bit_depth(png_ptr, info_ptr));
115 
116  if (img_cfp == NULL) {
117  cfclose(png_file);
118  png_file = NULL;
119  }
120 
121  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
122 
123  return PNG_ERROR_NONE;
124 }
125 
126 // Loads a PNG image
127 //
128 // filename - name of the targa file to load
129 // image_data - allocated storage for the bitmap
130 //
131 // returns - true if succesful, false otherwise
132 //
133 int png_read_bitmap(const char *real_filename, ubyte *image_data, ubyte *bpp, int dest_size, int cf_type)
134 {
136  png_infop info_ptr;
137  png_structp png_ptr;
138  png_bytepp row_pointers;
139  unsigned int i, len;
140 
141  png_file = NULL;
142 
143  strcpy_s( filename, real_filename );
144  char *p = strchr( filename, '.' );
145  if ( p ) *p = 0;
146  strcat_s( filename, ".png" );
147 
148  png_file = cfopen(filename, "rb", CFILE_NORMAL, cf_type);
149 
150  if (png_file == NULL)
151  return PNG_ERROR_READING;
152 
153  /* Create and initialize the png_struct with the desired error handler
154  * functions. If you want to use the default stderr and longjump method,
155  * you can supply NULL for the last three parameters. We also supply the
156  * the compiler header file version, so that we know if the application
157  * was compiled with a compatible version of the library. REQUIRED
158  */
159  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
160 
161  if (png_ptr == NULL)
162  {
163  mprintf(("png_read_bitmap: png_ptr went wrong\n"));
164  cfclose(png_file);
165  return PNG_ERROR_READING;
166  }
167 
168  /* Allocate/initialize the memory for image information. REQUIRED. */
169  info_ptr = png_create_info_struct(png_ptr);
170  if (info_ptr == NULL)
171  {
172  mprintf(("png_read_bitmap: info_ptr went wrong\n"));
173  cfclose(png_file);
174  png_destroy_read_struct(&png_ptr, NULL, NULL);
175  return PNG_ERROR_READING;
176  }
177 
178  if (setjmp(png_jmpbuf(png_ptr)))
179  {
180  mprintf(("png_read_bitmap: something went wrong\n"));
181  /* Free all of the memory associated with the png_ptr and info_ptr */
182  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
183  cfclose(png_file);
184  /* If we get here, we had a problem reading the file */
185  return PNG_ERROR_READING;
186  }
187 
188  png_set_read_fn(png_ptr, &png_file, png_scp_read_data);
189 
190  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
191  len = png_get_rowbytes(png_ptr, info_ptr);
192 
193  row_pointers = png_get_rows(png_ptr, info_ptr);
194 
195  if(bpp)
196  *bpp = (ubyte)(len / png_get_image_width(png_ptr, info_ptr)) << 3;
197 
198  //copy row data to image
199  unsigned int height = png_get_image_height(png_ptr, info_ptr);
200  for (i = 0; i < height; i++) {
201  memcpy(&image_data[i * len], row_pointers[i], len);
202  }
203 
204  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
205  cfclose(png_file);
206 
207  return PNG_ERROR_NONE;
208 }
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
CFILE * png_file
Definition: pngutils.cpp:12
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
Assert(pm!=NULL)
#define mprintf(args)
Definition: pstypes.h:238
int png_read_bitmap(const char *real_filename, ubyte *image_data, ubyte *bpp, int dest_size, int cf_type)
Definition: pngutils.cpp:133
Definition: cfile.h:28
#define PNG_ERROR_READING
Definition: pngutils.h:9
#define PNG_ERROR_NONE
Definition: pngutils.h:8
int png_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette)
Definition: pngutils.cpp:38
#define cfopen(...)
Definition: cfile.h:134
void png_scp_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
Definition: pngutils.cpp:15
char * filename
unsigned char ubyte
Definition: pstypes.h:62
GLint GLsizei GLsizei height
Definition: Gl.h:1505
#define strcat_s(...)
Definition: safe_strings.h:68
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
GLfloat GLfloat p
Definition: Glext.h:8373
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
GLenum GLuint GLenum GLsizei length
Definition: Glext.h:5156
GLenum GLsizei len
Definition: Glext.h:6283
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
#define strcpy_s(...)
Definition: safe_strings.h:67