/* ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net This code is covered by the GNU GPL licence */ #include "../Libraries/libpng/png.h" #include "CEMulatorCtrl.h" #include "../kegs/Src/video.h" #define abort_(X) { printf(X); return 0;} extern word32 g_a2palette_8to1624[256]; #ifdef DRIVER_OSX extern int macUsingCoreGraphics; #endif int savePNG(MyString& _path) { int _borderWidth = option.getIntValue(OPTION_PNGBORDER); _path = "({ \"error\" : \"Cannot create screenshot\" })"; CEmulator* pEmu = CEmulator::theEmulator ; int bootslot = pEmu->config->bootslot; MyString filename; CSlotInfo& slot = pEmu->getLocalIMGInfo(bootslot,1); printf(slot.shortname.c_str()); MyString filenoext; if (!slot.shortname.IsEmpty()) filenoext = getfilenoext(slot.shortname.c_str()); else filenoext = "nodisk"; int i=0; // CDownload dl; while(i<100) { filename.Format("%s%sscreenshot_%s_%d.png", CDownload::getPersistentPath(), ACTIVEGS_DIRECTORY_SEPARATOR, filenoext.c_str(), i); FILE* f=fopen(filename.c_str(),"rb"); if (!f) break; fclose(f); i++; } Kimage* kimage_ptr = g_video.g_a2_line_kimage[0]; int a2width ; int a2height; if (kimage_ptr == &s_video.g_kimage_superhires) { a2width = 320*VIDEO_HFACTOR; a2height=200*VIDEO_VFACTOR;; } else { kimage_ptr = &s_video.g_mainwin_kimage; a2width = 280*VIDEO_HFACTOR; a2height = 192*VIDEO_VFACTOR; } int width = a2width + _borderWidth*2; int height = a2height + _borderWidth*2; png_byte color_type =PNG_COLOR_TYPE_RGB; png_byte bit_depth = 8; png_structp png_ptr; png_infop info_ptr; png_bytep row_pointers[1024]; byte *pngraw = (byte*)malloc(width*height*3); int stride =kimage_ptr->width_act * kimage_ptr->mdepth / 8; int bcolor = g_a2palette_8to1624[g_video.g_border_color]; char border[3]; #ifdef DRIVER_OSX if (macUsingCoreGraphics) { border[0]=(char)bcolor; border[1]=(char)(bcolor >> 8); border[2]=(char)(bcolor >> 16); } else #endif { border[2]=(char)bcolor; border[1]=(char)(bcolor >> 8); border[0]=(char)(bcolor >> 16); } for(int i=0;i=(a2height+_borderWidth) || j<_borderWidth || j>=(a2width+_borderWidth) ) { dst[0]=border[0]; dst[1]=border[1]; dst[2]=border[2]; } else { byte* src= &kimage_ptr->data_ptr[(i-_borderWidth)*stride+(j-_borderWidth)* kimage_ptr->mdepth / 8]; #ifdef DRIVER_OSX if (macUsingCoreGraphics) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; } else #endif { dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; } } } } /* create file */ FILE *fp = fopen(filename.c_str(), "wb"); if (!fp) abort_("[write_png_file] File could not be opened for writing"); /* initialize stuff */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[write_png_file] png_create_write_struct failed"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("[write_png_file] png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during init_io"); png_init_io(png_ptr, fp); /* write header */ if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during writing header"); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); /* write bytes */ if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during writing bytes"); png_write_image(png_ptr, row_pointers); /* end write */ if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during end of write"); png_write_end(png_ptr, NULL); png_destroy_info_struct(png_ptr,&info_ptr); png_destroy_write_struct(&png_ptr,&info_ptr); png_free(png_ptr,NULL); free(pngraw); fclose(fp); outputInfo("screenshot %s saved\n",filename.c_str()); _path.Format("({ \"info\" : \"Screenshot saved : %s\", \"filename\" : \"%s\" })",getfile(filename.c_str()),filename.c_str()); return 1; }