|
|
1.1 ! root 1: /* ! 2: Hatari - screenSnapShot.c ! 3: ! 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. ! 8: */ ! 9: const char ScreenSnapShot_fileid[] = "Hatari screenSnapShot.c : " __DATE__ " " __TIME__; ! 10: ! 11: #include <SDL.h> ! 12: #include <dirent.h> ! 13: #include <string.h> ! 14: #include "main.h" ! 15: #include "log.h" ! 16: #include "paths.h" ! 17: #include "screen.h" ! 18: #include "screenSnapShot.h" ! 19: #include "video.h" ! 20: /* after above that bring in config.h */ ! 21: #if HAVE_LIBPNG ! 22: # include <png.h> ! 23: # include <assert.h> ! 24: # include "pixel_convert.h" /* inline functions */ ! 25: #endif ! 26: ! 27: ! 28: bool bRecordingAnimation = false; /* Recording animation? */ ! 29: static int nScreenShots = 0; /* Number of screen shots saved */ ! 30: ! 31: ! 32: /*-----------------------------------------------------------------------*/ ! 33: /** ! 34: * Scan working directory to get the screenshot number ! 35: */ ! 36: static void ScreenSnapShot_GetNum(void) ! 37: { ! 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); ! 69: } ! 70: ! 71: ! 72: #if HAVE_LIBPNG ! 73: /** ! 74: * Save given SDL surface as PNG. Return png file size > 0 for success. ! 75: */ ! 76: static int ScreenSnapShot_SavePNG(SDL_Surface *surface, const char *filename) ! 77: { ! 78: FILE *fp = NULL; ! 79: int ret; ! 80: ! 81: fp = fopen(filename, "wb"); ! 82: if (!fp) ! 83: return -1; ! 84: ! 85: ret = ScreenSnapShot_SavePNG_ToFile(surface, fp, -1, -1, 0, 0, 0, 0); /* default compression/filter and no cropping */ ! 86: ! 87: fclose (fp); ! 88: return ret; /* >0 if OK, -1 if error */ ! 89: } ! 90: ! 91: ! 92: /** ! 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. ! 96: */ ! 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 ) ! 99: { ! 100: bool do_lock; ! 101: int y, ret = -1; ! 102: int w = surface->w - CropLeft - CropRight; ! 103: int h = surface->h - CropTop - CropBottom; ! 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"; ! 113: long start; ! 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: ! 133: /* store current pos in fp (could be != 0 for avi recording) */ ! 134: start = ftell ( fp ); ! 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); ! 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: ! 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: ! 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); ! 164: for (y = 0; y < h; y++) { ! 165: /* need to lock the surface while accessing it directly */ ! 166: if (do_lock) ! 167: SDL_LockSurface(surface); ! 168: switch (fmt->BytesPerPixel) { ! 169: case 1: ! 170: /* unpack 8-bit data with RGB palette */ ! 171: row_ptr = rowbuf; ! 172: PixelConvert_8to24Bits(row_ptr, src_ptr, w, fmt->palette->colors); ! 173: break; ! 174: case 2: ! 175: /* unpack 16-bit RGB pixels */ ! 176: row_ptr = rowbuf; ! 177: PixelConvert_16to24Bits(row_ptr, (Uint16*)src_ptr, w, fmt); ! 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; ! 186: PixelConvert_32to24Bits(row_ptr, (Uint32*)src_ptr, w, fmt); ! 187: break; ! 188: } ! 189: /* and unlock surface before syscalls */ ! 190: if (do_lock) ! 191: SDL_UnlockSurface(surface); ! 192: src_ptr += surface->pitch; ! 193: png_write_row(png_ptr, rowbuf); ! 194: } ! 195: ! 196: /* write the additional chuncks to the PNG file */ ! 197: png_write_end(png_ptr, info_ptr); ! 198: ! 199: ret = ftell ( fp ) - start; /* size of the png image */ ! 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: /** ! 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. ! 215: */ ! 216: void ScreenSnapShot_SaveScreen(void) ! 217: { ! 218: char *szFileName = malloc(FILENAME_MAX); ! 219: ! 220: if (!szFileName) return; ! 221: ! 222: ScreenSnapShot_GetNum(); ! 223: /* Create our filename */ ! 224: nScreenShots++; ! 225: #if HAVE_LIBPNG ! 226: /* try first PNG */ ! 227: sprintf(szFileName,"%s/grab%4.4d.png", Paths_GetWorkingDir(), nScreenShots); ! 228: if (ScreenSnapShot_SavePNG(sdlscrn, szFileName) > 0) ! 229: { ! 230: fprintf(stderr, "Screen dump saved to: %s\n", szFileName); ! 231: free(szFileName); ! 232: return; ! 233: } ! 234: #endif ! 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); ! 240: ! 241: free(szFileName); ! 242: } ! 243:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.