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