"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