activegs-ios/Common/libpng.cpp

192 lines
4.5 KiB
C++

/*
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<height;i++)
{
byte* row = &pngraw[i*width*3];
row_pointers[i]=row;
for(int j=0;j<width;j++)
{
byte* dst= &row[j*3];
if ( i<_borderWidth || 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;
}