Advanced Strategic Command
surface2png.cpp
Go to the documentation of this file.
1 
2 /*
3  This file is part of Advanced Strategic Command; http://www.asc-hq.de
4  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; see the file COPYING. If not, write to the
18  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  Boston, MA 02111-1307 USA
20 */
21 
22 #ifdef NO_INTERNAL_PNG
23 #include <SDL_image.h>
24 #else
25 #include <png.h>
26 #endif
27 
28 #include "surface2png.h"
29 #include "../util/messaginghub.h"
30 
31 void writePNG( const ASCString& filename, const Surface& s )
32 {
33  writePNG( filename, s, 0,0, s.w(), s.h());
34 }
35 
36 void writePNGtrim( const ASCString& filename, const Surface& s )
37 {
38  int x2 = 0;
39  int y2 = 0;
40  int x1 = s.w();
41  int y1 = s.h();
42 
43  for ( int y = 0; y < s.h(); ++y )
44  for ( int x = 0; x < s.w(); ++x )
45  if ( s.GetPixelFormat().GetRGBA( s.GetPixel(x,y)).a != Surface::transparent ) {
46  x1 = min(x1, x);
47  y1 = min(y1, y);
48  x2 = max(x2, x);
49  y2 = max(y2, y);
50  }
51 
52  writePNG( filename, s, x1,y1, x2-x1+1, y2-y1+1);
53 }
54 
55 void writePNG( const ASCString& filename, const Surface& s, const SDLmm::SRect& rect )
56 {
57  writePNG( filename, s, rect.x, rect.y, rect.w, rect.h);
58 }
59 
60 
61 #ifdef NO_INTERNAL_PNG
62 
63 void writePNG( const ASCString& filename, const Surface& s, int x1, int y1, int w, int h )
64 {
65  if ( s.GetPixelFormat().BytesPerPixel () != 4 ) {
66  errorMessage("Only 32 Bit images are supported for PNG writing");
67  return;
68  }
69 
70  SDL_RWops *rw=SDL_RWFromFile( filename.c_str(),"wb");
71  if(rw==NULL) {
72  errorMessage("Could not open " + filename + " for writing");
73  return;
74  }
75 
76  IMG_WritePNG_RW( rw, s.GetSurface(), x1,y1,w,h);
77 
78  SDL_RWclose(rw);
79 
80 }
81 
82 #else
83 
84 void writePNG( const ASCString& filename, const Surface& s, int x1, int y1, int w, int h )
85 {
86 
87  if ( x1 < 0 )
88  x1 = 0;
89  if ( y1 < 0 )
90  y1 = 0;
91  if ( w >= s.w()-x1 )
92  w = s.w() -x1 ;
93  if ( h >= s.h()-y1 )
94  h = s.h() -y1 ;
95 
96  if ( s.GetPixelFormat().BytesPerPixel() != 4 && s.GetPixelFormat().BytesPerPixel() != 1 ) {
97  errorMessage("Only 8 Bit and 32 Bit images are supported for PNG writing");
98  return;
99  }
100 
101 
102  FILE* fp = fopen(filename.c_str(), "wb");
103  if( fp == NULL)
104  {
105  errorMessage("Could not open " + filename + " for writing");
106  return;
107  }
108 
109  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
110  png_infop info_ptr = png_create_info_struct(png_ptr);
111  png_init_io(png_ptr, fp);
112 
113  png_color my_palette[256];
114 
115  if ( s.GetPixelFormat().BytesPerPixel() == 4 ){
116  png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
117  } else {
118  png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
119 
120  SDL_Palette* sdlpal = s.GetPixelFormat().palette();
121  if ( sdlpal->ncolors > 256 ) {
122  errorMessage("A palettes with more than 256 colors is not supported");
123  return;
124  }
125 
126  for ( int c = 0; c < sdlpal->ncolors; ++c ) {
127  my_palette[c].red = sdlpal->colors[c].r;
128  my_palette[c].green = sdlpal->colors[c].g;
129  my_palette[c].blue = sdlpal->colors[c].b;
130  }
131 
132  png_set_PLTE(png_ptr, info_ptr, my_palette, sdlpal->ncolors);
133  }
134 
135  time_t gmt;
136  png_time mod_time;
137  time(&gmt);
138  png_convert_from_time_t(&mod_time, gmt);
139  png_set_tIME(png_ptr, info_ptr, &mod_time);
140 
141 
142  png_text text_ptr[1];
143  text_ptr[0].key = const_cast<char*>("Title");
144  text_ptr[0].text = const_cast<char*>("Advanced Strategic Command");
145  text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
146  png_set_text(png_ptr, info_ptr, text_ptr, 1);
147 
148 
149  Uint8* linebuf = new Uint8[w*4];
150 
151  png_write_info(png_ptr, info_ptr);
152 
153 
154  int iii = 0;
155  char* pix = (char*)s.pixels();
156  for ( int y = y1; y < y1 + h; ++y ) {
157  Uint32* srcpix32 = (Uint32*)(pix + y * s.pitch());
158  srcpix32 += x1;
159  Uint8* srcpix8 = (Uint8*)(pix + y * s.pitch());
160  srcpix8 += x1;
161  if ( s.GetPixelFormat().BytesPerPixel() == 4) {
162  for ( int x = 0; x < w; ++x )
163  s.GetPixelFormat().GetRGBA( srcpix32[x], linebuf[x*4],linebuf[x*4+1],linebuf[x*4+2],linebuf[x*4+3] );
164  } else {
165  if ( s.GetPixelFormat().BytesPerPixel() == 1)
166  for ( int x = 0; x < w; ++x ) {
167  linebuf[x] = srcpix8[x];
168  if ( linebuf[x] )
169  ++iii;
170  }
171  }
172  png_write_row(png_ptr, (png_bytep) linebuf);
173  }
174  delete[] linebuf;
175 
176  png_write_end(png_ptr, info_ptr);
177  png_destroy_write_struct(&png_ptr, &info_ptr);
178  fclose(fp);
179 }
180 #endif
181 
182 
static const Uint32 transparent
Definition: surface.h:65
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
void writePNG(const ASCString &filename, const Surface &s)
Definition: surface2png.cpp:31
void writePNGtrim(const ASCString &filename, const Surface &s)
Definition: surface2png.cpp:36
void errorMessage(const ASCString &string)
const T & max(const T &a, const T &b, const T &c)
Definition: misc.h:97
const T & min(const T &a, const T &b, const T &c)
Definition: misc.h:80