|
|
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; 41: DIR *workingdir = opendir(Paths_GetWorkingDir()); 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 */ 92: ret = ScreenSnapShot_SavePNG_ToFile(surface, 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.12 root 104: int ScreenSnapShot_SavePNG_ToFile(SDL_Surface *surface, FILE *fp, int png_compression_level, int png_filter , 105: int CropLeft , int CropRight , int CropTop , int CropBottom ) 1.1.1.9 root 106: { 1.1.1.12 root 107: bool do_lock; 1.1.1.9 root 108: int y, ret = -1; 1.1.1.12 root 109: int w = surface->w - CropLeft - CropRight; 110: int h = surface->h - CropTop - CropBottom; 1.1.1.13 root 111: Uint8 *src_ptr; 1.1.1.9 root 112: Uint8 rowbuf[3*surface->w]; 113: SDL_PixelFormat *fmt = surface->format; 114: png_colorp palette_ptr = NULL; 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.12 root 120: long start; 1.1.1.9 root 121: 122: /* Create and initialize the png_struct with error handler functions. */ 123: png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 124: if (!png_ptr) 125: { 126: return ret; 127: } 128: 129: /* Allocate/initialize the image information data. */ 130: info_ptr = png_create_info_struct(png_ptr); 131: if (!info_ptr) 132: goto png_cleanup; 133: 134: /* libpng ugliness: Set error handling when not supplying own 135: * error handling functions in the png_create_write_struct() call. 136: */ 137: if (setjmp(png_jmpbuf(png_ptr))) 138: goto png_cleanup; 139: 1.1.1.12 root 140: /* store current pos in fp (could be != 0 for avi recording) */ 141: start = ftell ( fp ); 1.1.1.9 root 142: 143: /* initialize the png structure */ 144: png_init_io(png_ptr, fp); 145: 146: /* image data properties */ 147: png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, 148: PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, 149: PNG_FILTER_TYPE_DEFAULT); 1.1.1.12 root 150: 151: if ( png_compression_level >= 0 ) 152: png_set_compression_level ( png_ptr , png_compression_level ); 153: if ( png_filter >= 0 ) 154: png_set_filter ( png_ptr , 0 , png_filter ); 155: 1.1.1.9 root 156: /* image info */ 157: pngtext.key = key; 158: pngtext.text = text; 159: pngtext.compression = PNG_TEXT_COMPRESSION_NONE; 160: #ifdef PNG_iTXt_SUPPORTED 161: pngtext.lang = NULL; 162: #endif 163: png_set_text(png_ptr, info_ptr, &pngtext, 1); 164: 165: /* write the file header information */ 166: png_write_info(png_ptr, info_ptr); 167: 1.1.1.12 root 168: /* write surface data rows one at a time (after cropping if necessary) */ 169: src_ptr = (Uint8 *)surface->pixels + CropTop * surface->pitch + CropLeft * surface->format->BytesPerPixel; 170: do_lock = SDL_MUSTLOCK(surface); 1.1.1.9 root 171: for (y = 0; y < h; y++) { 1.1.1.12 root 172: /* need to lock the surface while accessing it directly */ 173: if (do_lock) 174: SDL_LockSurface(surface); 1.1.1.9 root 175: switch (fmt->BytesPerPixel) { 176: case 1: 177: /* unpack 8-bit data with RGB palette */ 1.1.1.13 root 178: PixelConvert_8to24Bits(rowbuf, src_ptr, w, fmt->palette->colors); 1.1.1.9 root 179: break; 180: case 2: 181: /* unpack 16-bit RGB pixels */ 1.1.1.13 root 182: PixelConvert_16to24Bits(rowbuf, (Uint16*)src_ptr, w, fmt); 1.1.1.9 root 183: break; 184: case 3: 185: /* PNG can handle 24-bits */ 186: break; 187: case 4: 188: /* unpack 32-bit RGBA pixels */ 1.1.1.13 root 189: PixelConvert_32to24Bits(rowbuf, (Uint32*)src_ptr, w, fmt); 1.1.1.9 root 190: break; 191: } 1.1.1.12 root 192: /* and unlock surface before syscalls */ 193: if (do_lock) 194: SDL_UnlockSurface(surface); 1.1.1.9 root 195: src_ptr += surface->pitch; 196: png_write_row(png_ptr, rowbuf); 197: } 1.1.1.12 root 198: 1.1.1.9 root 199: /* write the additional chuncks to the PNG file */ 200: png_write_end(png_ptr, info_ptr); 201: 1.1.1.12 root 202: ret = ftell ( fp ) - start; /* size of the png image */ 1.1.1.9 root 203: png_cleanup: 204: if (palette_ptr) 205: free(palette_ptr); 206: if (png_ptr) 207: png_destroy_write_struct(&png_ptr, NULL); 208: return ret; 209: } 210: #endif 211: 212: 213: /*-----------------------------------------------------------------------*/ 214: /** 1.1.1.11 root 215: * Save screen shot file with filename like 'grab0000.[png|bmp]', 216: * 'grab0001.[png|bmp]', etc... Whether screen shots are saved as BMP 217: * or PNG depends on Hatari configuration. 1.1.1.8 root 218: */ 1.1 root 219: void ScreenSnapShot_SaveScreen(void) 220: { 1.1.1.8 root 221: char *szFileName = malloc(FILENAME_MAX); 1.1.1.6 root 222: 1.1.1.8 root 223: if (!szFileName) return; 1.1.1.5 root 224: 1.1.1.8 root 225: ScreenSnapShot_GetNum(); 226: /* Create our filename */ 227: nScreenShots++; 1.1.1.9 root 228: #if HAVE_LIBPNG 229: /* try first PNG */ 230: sprintf(szFileName,"%s/grab%4.4d.png", Paths_GetWorkingDir(), nScreenShots); 1.1.1.12 root 231: if (ScreenSnapShot_SavePNG(sdlscrn, szFileName) > 0) 1.1.1.9 root 232: { 233: fprintf(stderr, "Screen dump saved to: %s\n", szFileName); 234: free(szFileName); 235: return; 236: } 237: #endif 1.1.1.8 root 238: sprintf(szFileName,"%s/grab%4.4d.bmp", Paths_GetWorkingDir(), nScreenShots); 239: if (SDL_SaveBMP(sdlscrn, szFileName)) 240: fprintf(stderr, "Screen dump failed!\n"); 241: else 242: fprintf(stderr, "Screen dump saved to: %s\n", szFileName); 1.1.1.5 root 243: 1.1.1.8 root 244: free(szFileName); 1.1 root 245: } 246:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.