"Fossies" - the Fresh Open Source Software Archive 
Member "netmapr-1.9c/savepng.c" (14 Dec 2009, 7993 Bytes) of package /linux/privat/old/netmapr-1.9c.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "savepng.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 Based on zlib license - see http://www.gzip.org/zlib/zlib_license.html
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 "Philip D. Bober" <wildfire1138@mchsi.com>
21 */
22
23 #include <stdlib.h>
24 #include <SDL.h>
25 #include <SDL_byteorder.h>
26 #include <png.h>
27 #include "savepng.h"
28
29 int SavePNG(const char *file, SDL_Surface *surf,int compression){
30 SDL_RWops *fp;
31 int ret;
32
33 fp=SDL_RWFromFile(file,"wb");
34
35 if( fp == NULL ) {
36 return (-1);
37 }
38
39 ret=SavePNG_RW(fp,surf,compression);
40 SDL_RWclose(fp);
41 return ret;
42 }
43
44 static void png_write_data(png_structp png_ptr,png_bytep data, png_size_t length){
45 SDL_RWops *rp = (SDL_RWops*) png_get_io_ptr(png_ptr);
46 SDL_RWwrite(rp,data,1,length);
47 }
48
49 int SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
50 png_structp png_ptr;
51 png_infop info_ptr;
52 SDL_PixelFormat *fmt=NULL;
53 SDL_Surface *tempsurf=NULL;
54 int ret,funky_format,used_alpha;
55 unsigned int i,temp_alpha;
56 png_colorp palette;
57 Uint8 *palette_alpha=NULL;
58 png_byte **row_pointers=NULL;
59 png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1;
60 funky_format=0;
61
62 if( !src || !surf) {
63 goto savedone; /* Nothing to do. */
64 }
65
66 row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*));
67 if (!row_pointers) {
68 SDL_SetError("Couldn't allocate memory for rowpointers");
69 goto savedone;
70 }
71
72 png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
73 if (!png_ptr){
74 SDL_SetError("Couldn't allocate memory for PNG file");
75 goto savedone;
76 }
77 info_ptr= png_create_info_struct(png_ptr);
78 if (!info_ptr){
79 SDL_SetError("Couldn't allocate image information for PNG file");
80 goto savedone;
81 }
82 /* setup custom writer functions */
83 png_set_write_fn(png_ptr,(voidp)src,png_write_data,NULL);
84
85 /*
86 oooooo
87 if (setjmp(png_jmpbuf(png_ptr))){
88 SDL_SetError("Unknown error writing PNG");
89 goto savedone;
90 }
91 */
92
93 if(compression>Z_BEST_COMPRESSION)
94 compression=Z_BEST_COMPRESSION;
95
96 if(compression == Z_NO_COMPRESSION) // No compression
97 {
98 png_set_filter(png_ptr,0,PNG_FILTER_NONE);
99 png_set_compression_level(png_ptr,Z_NO_COMPRESSION);
100 }
101 else if(compression<0) // Default compression
102 png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION);
103 else
104 png_set_compression_level(png_ptr,compression);
105
106 fmt=surf->format;
107 if(fmt->BitsPerPixel==8){ /* Paletted */
108 png_set_IHDR(png_ptr,info_ptr,
109 surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE,
110 PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
111 PNG_FILTER_TYPE_DEFAULT);
112 palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color));
113 if (!palette) {
114 SDL_SetError("Couldn't create memory for palette");
115 goto savedone;
116 }
117 for (i=0;i<fmt->palette->ncolors;i++) {
118 palette[i].red=fmt->palette->colors[i].r;
119 palette[i].green=fmt->palette->colors[i].g;
120 palette[i].blue=fmt->palette->colors[i].b;
121 }
122 png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors);
123 if (surf->flags&SDL_SRCCOLORKEY) {
124 palette_alpha=(Uint8 *)malloc((fmt->colorkey+1)*sizeof(Uint8));
125 if (!palette_alpha) {
126 SDL_SetError("Couldn't create memory for palette transparency");
127 goto savedone;
128 }
129 /* FIXME: memset? */
130 for (i=0;i<(fmt->colorkey+1);i++) {
131 palette_alpha[i]=255;
132 }
133 palette_alpha[fmt->colorkey]=0;
134 png_set_tRNS(png_ptr,info_ptr,palette_alpha,fmt->colorkey+1,NULL);
135 }
136 }else{ /* Truecolor */
137 if (fmt->Amask) {
138 png_set_IHDR(png_ptr,info_ptr,
139 surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA,
140 PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
141 PNG_FILTER_TYPE_DEFAULT);
142 } else {
143 png_set_IHDR(png_ptr,info_ptr,
144 surf->w,surf->h,8,PNG_COLOR_TYPE_RGB,
145 PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
146 PNG_FILTER_TYPE_DEFAULT);
147 }
148 }
149 png_write_info(png_ptr, info_ptr);
150
151 if (fmt->BitsPerPixel==8) { /* Paletted */
152 for(i=0;i<surf->h;i++){
153 row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
154 }
155 if(SDL_MUSTLOCK(surf)){
156 SDL_LockSurface(surf);
157 }
158 png_write_image(png_ptr, row_pointers);
159 if(SDL_MUSTLOCK(surf)){
160 SDL_UnlockSurface(surf);
161 }
162 }else{ /* Truecolor */
163 if(fmt->BytesPerPixel==3){
164 if(fmt->Amask){ /* check for 24 bit with alpha */
165 funky_format=1;
166 }else{
167 /* Check for RGB/BGR/GBR/RBG/etc surfaces.*/
168 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
169 if(fmt->Rmask!=0xFF0000
170 || fmt->Gmask!=0x00FF00
171 || fmt->Bmask!=0x0000FF){
172 #else
173 if(fmt->Rmask!=0x0000FF
174 || fmt->Gmask!=0x00FF00
175 || fmt->Bmask!=0xFF0000){
176 #endif
177 funky_format=1;
178 }
179 }
180 }else if (fmt->BytesPerPixel==4){
181 if (!fmt->Amask) { /* check for 32bit but no alpha */
182 funky_format=1;
183 }else{
184 /* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/
185 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
186 if(fmt->Rmask!=0xFF000000
187 || fmt->Gmask!=0x00FF0000
188 || fmt->Bmask!=0x0000FF00
189 || fmt->Amask!=0x000000FF){
190 #else
191 if(fmt->Rmask!=0x000000FF
192 || fmt->Gmask!=0x0000FF00
193 || fmt->Bmask!=0x00FF0000
194 || fmt->Amask!=0xFF000000){
195 #endif
196 funky_format=1;
197 }
198 }
199 }else{ /* 555 or 565 16 bit color */
200 funky_format=1;
201 }
202 if (funky_format) {
203 /* Allocate non-funky format, and copy pixeldata in*/
204 if(fmt->Amask){
205 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
206 tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
207 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
208 #else
209 tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
210 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
211 #endif
212 }else{
213 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
214 tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
215 0xff0000, 0x00ff00, 0x0000ff, 0x00000000);
216 #else
217 tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
218 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000);
219 #endif
220 }
221 if(!tempsurf){
222 SDL_SetError("Couldn't allocate temp surface");
223 goto savedone;
224 }
225 if(surf->flags&SDL_SRCALPHA){
226 temp_alpha=fmt->alpha;
227 used_alpha=1;
228 SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */
229 }else{
230 used_alpha=0;
231 }
232 if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){
233 SDL_SetError("Couldn't blit surface to temp surface");
234 SDL_FreeSurface(tempsurf);
235 goto savedone;
236 }
237 if (used_alpha) {
238 SDL_SetAlpha(surf,SDL_SRCALPHA,(Uint8)temp_alpha); /* Restore alpha settings*/
239 }
240 for(i=0;i<tempsurf->h;i++){
241 row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch;
242 }
243 if(SDL_MUSTLOCK(tempsurf)){
244 SDL_LockSurface(tempsurf);
245 }
246 png_write_image(png_ptr, row_pointers);
247 if(SDL_MUSTLOCK(tempsurf)){
248 SDL_UnlockSurface(tempsurf);
249 }
250 SDL_FreeSurface(tempsurf);
251 } else {
252 for(i=0;i<surf->h;i++){
253 row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
254 }
255 if(SDL_MUSTLOCK(surf)){
256 SDL_LockSurface(surf);
257 }
258 png_write_image(png_ptr, row_pointers);
259 if(SDL_MUSTLOCK(surf)){
260 SDL_UnlockSurface(surf);
261 }
262 }
263 }
264
265 png_write_end(png_ptr, NULL);
266 ret=0; /* got here, so nothing went wrong. YAY! */
267
268 savedone: /* clean up and return */
269 png_destroy_write_struct(&png_ptr,&info_ptr);
270 if (palette) {
271 free(palette);
272 }
273 if (palette_alpha) {
274 free(palette_alpha);
275 }
276 if (row_pointers) {
277 free(row_pointers);
278 }
279 return ret;
280 }
281