|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - screenSnapShot.c
1.1 root 3:
1.1.1.5 root 4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Screen Snapshots.
1.1 root 8: */
1.1.1.11 root 9: const char ScreenSnapShot_fileid[] = "Hatari screenSnapShot.c : " __DATE__ " " __TIME__;
1.1 root 10:
1.1.1.2 root 11: #include <SDL.h>
12: #include <dirent.h>
13: #include <string.h>
1.1 root 14: #include "main.h"
1.1.1.6 root 15: #include "log.h"
1.1.1.8 root 16: #include "paths.h"
1.1 root 17: #include "screen.h"
18: #include "screenSnapShot.h"
19: #include "video.h"
1.1.1.9 root 20: /* after above that bring in config.h */
21: #if HAVE_LIBPNG
22: # include <png.h>
23: # include <assert.h>
1.1.1.12! root 24: # include "pixel_convert.h" /* inline functions */
1.1.1.9 root 25: #endif
1.1 root 26:
1.1.1.2 root 27:
1.1.1.11 root 28: bool bRecordingAnimation = false; /* Recording animation? */
1.1.1.6 root 29: static int nScreenShots = 0; /* Number of screen shots saved */
30:
1.1 root 31:
1.1.1.2 root 32: /*-----------------------------------------------------------------------*/
1.1.1.8 root 33: /**
34: * Scan working directory to get the screenshot number
35: */
1.1.1.5 root 36: static void ScreenSnapShot_GetNum(void)
37: {
1.1.1.8 root 38: char dummy[5];
39: int i, num;
40: DIR *workingdir = opendir(Paths_GetWorkingDir());
41: struct dirent *file;
42:
43: nScreenShots = 0;
44: if (workingdir == NULL) return;
45:
46: file = readdir(workingdir);
47: while (file != NULL)
48: {
49: if ( strncmp("grab", file->d_name, 4) == 0 )
50: {
51: /* copy next 4 numbers */
52: for (i = 0; i < 4; i++)
53: {
54: if (file->d_name[4+i] >= '0' && file->d_name[4+i] <= '9')
55: dummy[i] = file->d_name[4+i];
56: else
57: break;
58: }
59:
60: dummy[i] = '\0'; /* null terminate */
61: num = atoi(dummy);
62: if (num > nScreenShots) nScreenShots = num;
63: }
64: /* next file.. */
65: file = readdir(workingdir);
66: }
67:
68: closedir(workingdir);
1.1.1.2 root 69: }
70:
1.1.1.8 root 71:
1.1.1.9 root 72: #if HAVE_LIBPNG
1.1.1.8 root 73: /**
1.1.1.12! root 74: * Save given SDL surface as PNG. Return png file size > 0 for success.
1.1.1.9 root 75: */
1.1.1.12! root 76: static int ScreenSnapShot_SavePNG(SDL_Surface *surface, const char *filename)
1.1.1.9 root 77: {
1.1.1.12! root 78: FILE *fp = NULL;
! 79: int ret;
! 80:
! 81: fp = fopen(filename, "wb");
! 82: if (!fp)
! 83: return -1;
1.1.1.9 root 84:
1.1.1.12! root 85: ret = ScreenSnapShot_SavePNG_ToFile(surface, fp, -1, -1, 0, 0, 0, 0); /* default compression/filter and no cropping */
1.1.1.9 root 86:
1.1.1.12! root 87: fclose (fp);
! 88: return ret; /* >0 if OK, -1 if error */
1.1.1.9 root 89: }
90:
1.1.1.12! root 91:
1.1.1.9 root 92: /**
1.1.1.12! root 93: * Save given SDL surface as PNG in an already opened FILE, eventually cropping some borders.
! 94: * Return png file size > 0 for success.
! 95: * This function is also used by avi_record.c to save individual frames as png images.
1.1.1.9 root 96: */
1.1.1.12! root 97: int ScreenSnapShot_SavePNG_ToFile(SDL_Surface *surface, FILE *fp, int png_compression_level, int png_filter ,
! 98: int CropLeft , int CropRight , int CropTop , int CropBottom )
1.1.1.9 root 99: {
1.1.1.12! root 100: bool do_lock;
1.1.1.9 root 101: int y, ret = -1;
1.1.1.12! root 102: int w = surface->w - CropLeft - CropRight;
! 103: int h = surface->h - CropTop - CropBottom;
1.1.1.9 root 104: Uint8 *src_ptr, *row_ptr;
105: Uint8 rowbuf[3*surface->w];
106: SDL_PixelFormat *fmt = surface->format;
107: png_colorp palette_ptr = NULL;
108: png_infop info_ptr = NULL;
109: png_structp png_ptr;
110: png_text pngtext;
111: char key[] = "Title";
112: char text[] = "Hatari screenshot";
1.1.1.12! root 113: long start;
1.1.1.9 root 114:
115: /* Create and initialize the png_struct with error handler functions. */
116: png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
117: if (!png_ptr)
118: {
119: return ret;
120: }
121:
122: /* Allocate/initialize the image information data. */
123: info_ptr = png_create_info_struct(png_ptr);
124: if (!info_ptr)
125: goto png_cleanup;
126:
127: /* libpng ugliness: Set error handling when not supplying own
128: * error handling functions in the png_create_write_struct() call.
129: */
130: if (setjmp(png_jmpbuf(png_ptr)))
131: goto png_cleanup;
132:
1.1.1.12! root 133: /* store current pos in fp (could be != 0 for avi recording) */
! 134: start = ftell ( fp );
1.1.1.9 root 135:
136: /* initialize the png structure */
137: png_init_io(png_ptr, fp);
138:
139: /* image data properties */
140: png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB,
141: PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
142: PNG_FILTER_TYPE_DEFAULT);
1.1.1.12! root 143:
! 144: if ( png_compression_level >= 0 )
! 145: png_set_compression_level ( png_ptr , png_compression_level );
! 146: if ( png_filter >= 0 )
! 147: png_set_filter ( png_ptr , 0 , png_filter );
! 148:
1.1.1.9 root 149: /* image info */
150: pngtext.key = key;
151: pngtext.text = text;
152: pngtext.compression = PNG_TEXT_COMPRESSION_NONE;
153: #ifdef PNG_iTXt_SUPPORTED
154: pngtext.lang = NULL;
155: #endif
156: png_set_text(png_ptr, info_ptr, &pngtext, 1);
157:
158: /* write the file header information */
159: png_write_info(png_ptr, info_ptr);
160:
1.1.1.12! root 161: /* write surface data rows one at a time (after cropping if necessary) */
! 162: src_ptr = (Uint8 *)surface->pixels + CropTop * surface->pitch + CropLeft * surface->format->BytesPerPixel;
! 163: do_lock = SDL_MUSTLOCK(surface);
1.1.1.9 root 164: for (y = 0; y < h; y++) {
1.1.1.12! root 165: /* need to lock the surface while accessing it directly */
! 166: if (do_lock)
! 167: SDL_LockSurface(surface);
1.1.1.9 root 168: switch (fmt->BytesPerPixel) {
169: case 1:
170: /* unpack 8-bit data with RGB palette */
171: row_ptr = rowbuf;
1.1.1.12! root 172: PixelConvert_8to24Bits(row_ptr, src_ptr, w, fmt->palette->colors);
1.1.1.9 root 173: break;
174: case 2:
175: /* unpack 16-bit RGB pixels */
176: row_ptr = rowbuf;
1.1.1.12! root 177: PixelConvert_16to24Bits(row_ptr, (Uint16*)src_ptr, w, fmt);
1.1.1.9 root 178: break;
179: case 3:
180: /* PNG can handle 24-bits */
181: row_ptr = src_ptr;
182: break;
183: case 4:
184: /* unpack 32-bit RGBA pixels */
185: row_ptr = rowbuf;
1.1.1.12! root 186: PixelConvert_32to24Bits(row_ptr, (Uint32*)src_ptr, w, fmt);
1.1.1.9 root 187: break;
188: }
1.1.1.12! root 189: /* and unlock surface before syscalls */
! 190: if (do_lock)
! 191: SDL_UnlockSurface(surface);
1.1.1.9 root 192: src_ptr += surface->pitch;
193: png_write_row(png_ptr, rowbuf);
194: }
1.1.1.12! root 195:
1.1.1.9 root 196: /* write the additional chuncks to the PNG file */
197: png_write_end(png_ptr, info_ptr);
198:
1.1.1.12! root 199: ret = ftell ( fp ) - start; /* size of the png image */
1.1.1.9 root 200: png_cleanup:
201: if (palette_ptr)
202: free(palette_ptr);
203: if (png_ptr)
204: png_destroy_write_struct(&png_ptr, NULL);
205: return ret;
206: }
207: #endif
208:
209:
210: /*-----------------------------------------------------------------------*/
211: /**
1.1.1.11 root 212: * Save screen shot file with filename like 'grab0000.[png|bmp]',
213: * 'grab0001.[png|bmp]', etc... Whether screen shots are saved as BMP
214: * or PNG depends on Hatari configuration.
1.1.1.8 root 215: */
1.1 root 216: void ScreenSnapShot_SaveScreen(void)
217: {
1.1.1.8 root 218: char *szFileName = malloc(FILENAME_MAX);
1.1.1.6 root 219:
1.1.1.8 root 220: if (!szFileName) return;
1.1.1.5 root 221:
1.1.1.8 root 222: ScreenSnapShot_GetNum();
223: /* Create our filename */
224: nScreenShots++;
1.1.1.9 root 225: #if HAVE_LIBPNG
226: /* try first PNG */
227: sprintf(szFileName,"%s/grab%4.4d.png", Paths_GetWorkingDir(), nScreenShots);
1.1.1.12! root 228: if (ScreenSnapShot_SavePNG(sdlscrn, szFileName) > 0)
1.1.1.9 root 229: {
230: fprintf(stderr, "Screen dump saved to: %s\n", szFileName);
231: free(szFileName);
232: return;
233: }
234: #endif
1.1.1.8 root 235: sprintf(szFileName,"%s/grab%4.4d.bmp", Paths_GetWorkingDir(), nScreenShots);
236: if (SDL_SaveBMP(sdlscrn, szFileName))
237: fprintf(stderr, "Screen dump failed!\n");
238: else
239: fprintf(stderr, "Screen dump saved to: %s\n", szFileName);
1.1.1.5 root 240:
1.1.1.8 root 241: free(szFileName);
1.1 root 242: }
243:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.