~ubuntu-branches/ubuntu/intrepid/zsnes/intrepid-proposed

« back to all changes in this revision

Viewing changes to src/zip/zpng.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-06-04 21:46:47 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070604214647-j5zowa8vplkug0yj
Tags: 1.510-1
* New upstream release - all patches merged. closes: #380734, #419270
* Add a .desktop file, thanks Nicholas Wheeler. closes: #367942
* Include a ton of documentation that ships with the tarball.
  closes: #392143 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
#include "zpng.h"
3
 
 
4
 
 
 
1
/*
 
2
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
 
3
 
 
4
http://www.zsnes.com
 
5
http://sourceforge.net/projects/zsnes
 
6
https://zsnes.bountysource.com
 
7
 
 
8
This program is free software; you can redistribute it and/or
 
9
modify it under the terms of the GNU General Public License
 
10
version 2 as published by the Free Software Foundation.
 
11
 
 
12
This program is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program; if not, write to the Free Software
 
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
*/
 
21
 
 
22
#ifndef NO_PNG
 
23
#include <png.h>
 
24
#endif
 
25
 
 
26
#ifdef __UNIXSDL__
 
27
#include "../gblhdr.h"
 
28
#else
 
29
#include <stdlib.h>
5
30
#ifdef __WIN32__
6
 
        #include <windows.h>
7
 
        #include <sys/stat.h>
8
 
        
9
 
        #ifdef __WIN32DBG__
10
 
                #include <crtdbg.h>
11
 
        #endif
12
 
#endif
13
 
 
14
 
#ifdef __MSDOS__
15
 
        #include <sys/types.h>
16
 
        #include <sys/stat.h>
17
 
        #include <unistd.h>
18
 
        #include <stdlib.h>
19
 
#endif
20
 
 
21
 
#ifdef __LINUX__
22
 
#include "../gblhdr.h"
23
 
#endif
24
 
 
25
 
extern unsigned int vidbuffer;
26
 
 
27
 
#ifdef __PNG__
28
 
 
29
 
int Png_Dump(const char * filename, unsigned short width, unsigned short height, unsigned char * image_data, bool usebgr)
30
 
{
31
 
        png_structp png_ptr;
32
 
        png_infop info_ptr;
33
 
        png_bytep * row_pointers;
34
 
        /*Set scanline width for 32-bit color data*/
35
 
        int scanline=width*4;
36
 
        int i; /*counter.*/
37
 
        int png_transforms=0;
38
 
        png_color fake_pal;
39
 
        /*Try to open the file.*/
40
 
        FILE *fp = fopen(filename, "wb");
41
 
        if (!fp)
42
 
        {
43
 
                return (-1);
44
 
        }
45
 
        
46
 
        fake_pal.red = 0;
47
 
        fake_pal.green = 0;
48
 
        fake_pal.blue = 0;
49
 
        /*Try to create png write struct, fail if we cannot.*/
50
 
        png_ptr = png_create_write_struct
51
 
                (PNG_LIBPNG_VER_STRING, NULL,/*(png_voidp)user_error_ptr,
52
 
                user_error_fn*/NULL, NULL/*user_warning_fn*/);
53
 
                if (!png_ptr)
54
 
                        return (-1);
55
 
                                                
56
 
        /*set png I/O source.*/
57
 
        png_init_io(png_ptr, fp);
58
 
                                                
59
 
        /* set the zlib compression level */
60
 
        png_set_compression_level(png_ptr,
61
 
                Z_BEST_COMPRESSION);
62
 
        
63
 
        /* set other zlib parameters */
64
 
        png_set_compression_mem_level(png_ptr, 8);
65
 
        png_set_compression_strategy(png_ptr,
66
 
                Z_DEFAULT_STRATEGY);
67
 
        png_set_compression_window_bits(png_ptr, 15);
68
 
        png_set_compression_method(png_ptr, 8);
69
 
        png_set_compression_buffer_size(png_ptr, 8192);
70
 
 
71
 
        /*try to create info struct. Fail and delete existing structs if info struct cannot be created.*/
72
 
        info_ptr = png_create_info_struct(png_ptr);
73
 
        if (!info_ptr)
74
 
        {
75
 
                png_destroy_write_struct(&png_ptr,
76
 
                        (png_infopp)NULL);
77
 
                        return (-1);
78
 
        }
79
 
 
80
 
        
81
 
        /*set a lot of image info (code adapted from libpng documentation!)*/
82
 
        png_set_IHDR(png_ptr, info_ptr, width, height,
83
 
                8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
84
 
                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
85
 
        
86
 
        info_ptr->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
87
 
 
88
 
        /*Allocate an array of scanline pointers*/
89
 
        row_pointers=(png_bytep*)malloc(height*sizeof(png_bytep));
90
 
        for (i=0;i<height;i++)
91
 
        {
92
 
#ifdef __UPSIDE_DOWN__
93
 
                /*invert to normal image format.*/
94
 
                row_pointers[i]=&image_data[scanline*(height-i-1)];
95
 
#else
96
 
                row_pointers[i]=&image_data[scanline*i];
97
 
#endif
98
 
        }
99
 
 
100
 
        /*tell the png library what to encode.*/
101
 
        png_set_rows(png_ptr, info_ptr, row_pointers);
102
 
 
103
 
        if(usebgr)
104
 
                png_transforms|=PNG_TRANSFORM_BGR;
105
 
        /*Write image to file*/
106
 
        png_write_png(png_ptr, info_ptr, png_transforms, NULL);
107
 
 
108
 
        /*close file*/
109
 
        fclose(fp);
110
 
        
111
 
        /*Destroy PNG structs*/
112
 
        png_destroy_write_struct(&png_ptr, &info_ptr);
113
 
        
114
 
        /*clean up dynamically allocated RAM.*/
115
 
        free(row_pointers);
116
 
 
117
 
#ifdef __WIN32DBG__
118
 
        _CrtDumpMemoryLeaks();
119
 
#endif
120
 
        return 0;
121
 
}
122
 
 
123
 
char *generate_filename(void)
124
 
{
125
 
        extern char fnames;
126
 
        char *filename;
127
 
        char *tmp = &fnames;
128
 
        char *tmp2 = 0;
129
 
        short i=0;
130
 
        struct stat buf;
131
 
 
132
 
#ifdef __MSDOS__
133
 
        filename = (char *)malloc(14);
134
 
        for(i=0;i<10000;i++)
135
 
        {
136
 
                if(i>1000)
137
 
                        sprintf(filename, "Image%03d.png", i);
138
 
                else sprintf(filename, "Imag%04d.png", i);
139
 
                if(stat(filename, &buf)==-1)
140
 
                        break;
141
 
        }
142
 
        return filename;
143
 
#endif
144
 
 
145
 
        tmp++;         // the first char is the string length
146
 
        // removes the path if there is one
147
 
        while (*tmp!=0) tmp++;
148
 
        while ((*tmp!='/') && (tmp!=&fnames)) tmp--;
149
 
        tmp++;
150
 
        // allocates enough memory to store the filename
151
 
        filename = (char *)malloc(strlen(tmp)+10);
152
 
        strcpy(filename, tmp);
153
 
 
154
 
        tmp = filename+strlen(filename);
155
 
        while (*tmp!='.') tmp--;
156
 
 
157
 
#ifdef __LINUX__
158
 
        tmp2 = filename;
159
 
        while (tmp2<tmp) {
160
 
          if (*tmp2 == ' ') *tmp2 = '_';
161
 
          tmp2++;
162
 
        }
163
 
#endif
164
 
 
165
 
        /*find first unused file*/
166
 
 
167
 
        /*Note: this results in a 9999 image limit!*/
168
 
 
169
 
        for(i=0;i<10000;i++)
170
 
        {
171
 
#ifdef __LINUX__
172
 
          sprintf(tmp, "_%04d.png", i);
173
 
#else
174
 
          sprintf(tmp, " %04d.png", i);
175
 
#endif
176
 
          if(stat(filename, &buf)==-1)
177
 
            break;
178
 
        }
179
 
 
180
 
        return filename;
181
 
}
182
 
 
183
 
#define SNAP_HEIGHT 223
184
 
void Grab_PNG_Data(void)
185
 
{
186
 
         char *filename;
187
 
         bool is_bgr_data=true;
188
 
 
189
 
        /*These are the variables used to perform the 32-bit conversion*/
190
 
        int i,j;
191
 
        unsigned short* pixel;
192
 
        unsigned short conv_pixel;
193
 
        /*Set scanline width for 32-bit color data: 4*256 = 1024*/
194
 
        int scanline=1024;
195
 
        unsigned char *DIBits;
196
 
        unsigned int * DBits;
197
 
 
198
 
        filename = generate_filename();
199
 
 
200
 
        /*Allocate image buffer for DIB data*/
201
 
        DIBits=(unsigned char*)malloc(scanline*SNAP_HEIGHT);
202
 
 
203
 
        /*Cast pointer to 32-bit data type*/
204
 
        DBits=(unsigned int*) DIBits;
205
 
 
206
 
        /*Use zsKnight's 16 to 32 bit color conversion*/
207
 
        pixel=(unsigned short*)(vidbuffer);
208
 
        for(i=0;i<SNAP_HEIGHT;i++)
209
 
        {
210
 
                for(j=0;j<256;j++)
211
 
                {
212
 
 
213
 
                        conv_pixel=pixel[(i*288)+j+16];
214
 
                        DBits[i*256+j]=((conv_pixel&0xF800)<<8)|
215
 
                                       ((conv_pixel&0x07E0)<<5)|
216
 
                                       ((conv_pixel&0x001F)<<3)|0xFF000000;
217
 
                }
218
 
        }
219
 
 
220
 
        /*compress and write the PNG*/
221
 
        Png_Dump(filename, 256, SNAP_HEIGHT, DIBits, is_bgr_data);
222
 
 
223
 
        free(DIBits);
224
 
        free(filename);
225
 
 
226
 
#ifdef __WIN32DBG__
227
 
        _CrtDumpMemoryLeaks();
228
 
#endif
229
 
 
230
 
}
231
 
 
232
 
#endif
 
31
#include <io.h>
 
32
#else
 
33
#include <unistd.h>
 
34
#endif
 
35
#endif
 
36
#include "../zpath.h"
 
37
 
 
38
#define NUMCONV_FW2
 
39
#define NUMCONV_FW3
 
40
#define NUMCONV_FW4
 
41
#include "../numconv.h"
 
42
 
 
43
#ifdef __MSDOS__
 
44
#define MAX_PNGNAME_LEN 13
 
45
#else
 
46
#define MAX_PNGNAME_LEN (strlen(ZSaveName)+11) //11 = _12345.png\0
 
47
#endif
 
48
 
 
49
char *generate_image_filename(const char *image_suffix)
 
50
{
 
51
  char *filename = (char *)malloc(MAX_PNGNAME_LEN);
 
52
  if (filename)
 
53
  {
 
54
    unsigned int i;
 
55
#ifdef __MSDOS__
 
56
    char *p = filename+3;
 
57
    strcpy(filename, "img");
 
58
#else
 
59
    char *p;
 
60
    strcpy(filename, ZSaveName);
 
61
    p = strrchr(filename, '.');
 
62
    if (!p) { p = filename+strlen(filename); }
 
63
    *p++ = '_';
 
64
#endif
 
65
    for (i = 0; i < 100000; i++)
 
66
    {
 
67
      sprintf(p, "%05d.%s", i, image_suffix);
 
68
      if (access_dir(ZSnapPath, filename, F_OK))
 
69
      {
 
70
        break;
 
71
      }
 
72
    }
 
73
    if (i == 100000)
 
74
    {
 
75
      free(filename);
 
76
      filename = 0;
 
77
    }
 
78
  }
 
79
  return(filename);
 
80
}
 
81
 
 
82
extern unsigned short *vidbuffer;
 
83
extern unsigned short resolutn;
 
84
 
 
85
#define SNAP_HEIGHT resolutn
 
86
#define SNAP_WIDTH 256
 
87
#define PIXEL (vidbuffer[((y+1)*288) + x + 16])
 
88
 
 
89
#ifndef NO_PNG
 
90
 
 
91
#define PIXEL_SIZE 3
 
92
int Png_Dump(const char *filename, unsigned short width, unsigned short height, unsigned char *image_data, bool usebgr)
 
93
{
 
94
  FILE *fp = fopen_dir(ZSnapPath, filename, "wb");
 
95
  if (fp)
 
96
  {
 
97
    //Try to create png write struct, fail if we cannot.
 
98
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
 
99
    if (png_ptr)
 
100
    {
 
101
      png_infop info_ptr;
 
102
 
 
103
      //set png I/O source.
 
104
      png_init_io(png_ptr, fp);
 
105
 
 
106
      //set the zlib compression level
 
107
      png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
 
108
 
 
109
      //set other zlib parameters
 
110
      png_set_compression_mem_level(png_ptr, 8);
 
111
      png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
 
112
      png_set_compression_window_bits(png_ptr, 15);
 
113
      png_set_compression_method(png_ptr, 8);
 
114
      png_set_compression_buffer_size(png_ptr, 8192);
 
115
 
 
116
      //try to create info struct. Fail and delete existing structs if info struct cannot be created.
 
117
      info_ptr = png_create_info_struct(png_ptr);
 
118
      if (info_ptr)
 
119
      {
 
120
        png_bytep *row_pointers;
 
121
 
 
122
        //Set scanline width for 32-bit color data
 
123
        unsigned int scanline = width*PIXEL_SIZE;
 
124
        int png_transforms = 0;
 
125
 
 
126
        unsigned int i;
 
127
 
 
128
        //set a lot of image info (code adapted from libpng documentation!)
 
129
        png_set_IHDR(png_ptr, info_ptr, width, height, 8,
 
130
                     PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
 
131
                     PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
132
        info_ptr->color_type = PNG_COLOR_TYPE_RGB;
 
133
 
 
134
        //Allocate an array of scanline pointers
 
135
        row_pointers = (png_bytep*)malloc(height*sizeof(png_bytep));
 
136
        for (i = 0; i < height; i++)
 
137
        {
 
138
          #ifdef __UPSIDE_DOWN__
 
139
          //invert to normal image format.
 
140
          row_pointers[i] = image_data + scanline*(height-i-1);
 
141
          #else
 
142
          row_pointers[i] = image_data + scanline*i;
 
143
          #endif
 
144
        }
 
145
 
 
146
        //tell the png library what to encode.
 
147
        png_set_rows(png_ptr, info_ptr, row_pointers);
 
148
 
 
149
        if (usebgr) { png_transforms|=PNG_TRANSFORM_BGR; }
 
150
        //Write image to file
 
151
        png_write_png(png_ptr, info_ptr, png_transforms, NULL);
 
152
        fclose(fp);
 
153
 
 
154
        //Destroy PNG structs
 
155
        png_destroy_write_struct(&png_ptr, &info_ptr);
 
156
 
 
157
        //clean up dynamically allocated RAM.
 
158
        free(row_pointers);
 
159
 
 
160
        return(0);
 
161
      }
 
162
      png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
 
163
    }
 
164
    fclose(fp);
 
165
  }
 
166
  return(-1);
 
167
}
 
168
 
 
169
void Grab_PNG_Data()
 
170
{
 
171
  char *filename = generate_image_filename("png");
 
172
  if (filename)
 
173
  {
 
174
    unsigned char *DBits = (unsigned char *)malloc(SNAP_HEIGHT*SNAP_WIDTH*PIXEL_SIZE);
 
175
    if (DBits)
 
176
    {
 
177
      //These are the variables used to perform the 24-bit conversion
 
178
      unsigned int y = SNAP_HEIGHT, x;
 
179
      // We can fill the array in any order, so might as well optimize loops
 
180
      while (y--)
 
181
      {
 
182
        for (x=SNAP_WIDTH ; x-- ;)
 
183
        {
 
184
          DBits[PIXEL_SIZE*(y*SNAP_WIDTH+x)]   = (PIXEL&0xF800) >> 8;
 
185
          DBits[PIXEL_SIZE*(y*SNAP_WIDTH+x)+1] = (PIXEL&0x07E0) >> 3;
 
186
          DBits[PIXEL_SIZE*(y*SNAP_WIDTH+x)+2] = (PIXEL&0x001F) << 3;
 
187
        }
 
188
      }
 
189
      //compress and write the PNG
 
190
      Png_Dump(filename, SNAP_WIDTH, SNAP_HEIGHT, DBits, false);
 
191
      free(DBits);
 
192
    }
 
193
    free(filename);
 
194
  }
 
195
}
 
196
 
 
197
#endif
 
198
 
 
199
void Grab_BMP_Data()
 
200
{
 
201
  char *filename = generate_image_filename("bmp");
 
202
  if (filename)
 
203
  {
 
204
    FILE *fp = fopen_dir(ZSnapPath, filename, "wb");
 
205
    if (fp)
 
206
    {
 
207
      const unsigned int header_size = 26;
 
208
      const unsigned short width = SNAP_WIDTH;
 
209
      const unsigned short height = SNAP_HEIGHT;
 
210
      unsigned short y = height, x;
 
211
 
 
212
      fputs("BM", fp);                            //Header
 
213
      fwrite4(width*height*3+header_size, fp);    //File size
 
214
      fwrite4(0, fp);                             //Reserved
 
215
      fwrite4(header_size, fp);                   //Offset to bitmap
 
216
      fwrite4(12, fp);                            //Length of color explain field;
 
217
      fwrite2(width, fp);                         //Width
 
218
      fwrite2(height, fp);                        //Height
 
219
      fwrite2(1, fp);                             //Planes
 
220
      fwrite2(24, fp);                            //Bits per pixel
 
221
 
 
222
      while (y--) //Have to write image upside down
 
223
      {
 
224
        for (x = 0; x < width; x++)
 
225
        {
 
226
          fwrite3(((PIXEL&0xF800) << 8) | ((PIXEL&0x07E0) << 5) | ((PIXEL&0x001F) << 3), fp);
 
227
        }
 
228
      }
 
229
      fclose(fp);
 
230
    }
 
231
    free(filename);
 
232
  }
 
233
}
 
234
 
 
235
void Grab_BMP_Data_8()
 
236
{
 
237
  char *filename = generate_image_filename("bmp");
 
238
  if (filename)
 
239
  {
 
240
    FILE *fp = fopen_dir(ZSnapPath, filename, "wb");
 
241
    if (fp)
 
242
    {
 
243
      const unsigned int colors = 256;
 
244
      const unsigned int palette_size = colors*4;
 
245
      const unsigned int header_size = palette_size+54;
 
246
      const unsigned short width = SNAP_WIDTH;
 
247
      const unsigned short height = SNAP_HEIGHT;
 
248
      unsigned short y, x;
 
249
 
 
250
      fputs("BM", fp);                          //Header
 
251
      fwrite4(width*height+header_size, fp);    //File size
 
252
      fwrite4(0, fp);                           //Reserved
 
253
      fwrite4(header_size, fp);                 //Offset to bitmap
 
254
      fwrite4(40, fp);                          //Length of color explain field;
 
255
      fwrite4(width, fp);                       //Width
 
256
      fwrite4(height, fp);                      //Height
 
257
      fwrite2(1, fp);                           //Planes
 
258
      fwrite2(8, fp);                           //Bits per pixel
 
259
      fwrite4(0, fp);                           //Compression Format
 
260
      fwrite4(width*height, fp);                //Bitmap data size
 
261
      fwrite4(0, fp);                           //H-Res?
 
262
      fwrite4(0, fp);                           //V-Res?
 
263
      fwrite4(colors, fp);                      //Colors
 
264
      fwrite4(colors, fp);                      //Important Colors
 
265
 
 
266
      for (y = 0; y < colors; y++) //Write palette
 
267
      {
 
268
        unsigned char byte = 0;
 
269
        fwrite((unsigned char *)vidbuffer+100000+y*3+3, 1, 1, fp);
 
270
        fwrite((unsigned char *)vidbuffer+100000+y*3+2, 1, 1, fp);
 
271
        fwrite((unsigned char *)vidbuffer+100000+y*3+1, 1, 1, fp);
 
272
        fwrite(&byte, 1, 1, fp);
 
273
      }
 
274
 
 
275
      for (y = height; y-- ;) //Have to write image upside down
 
276
      {
 
277
        for (x = 0; x < width; x++)
 
278
        {
 
279
          fwrite((unsigned char *)vidbuffer+(y+1)*288+x+16, 1, 1, fp);
 
280
        }
 
281
      }
 
282
      fclose(fp);
 
283
    }
 
284
    free(filename);
 
285
  }
 
286
}