unify screenshot code
no need to have the same code three times also: have jpegenc use our stream lib
This commit is contained in:
+21
-26
@@ -12,14 +12,13 @@ typedef unsigned short int WORD;
|
||||
typedef unsigned long int DWORD;
|
||||
typedef signed long int SDWORD;
|
||||
|
||||
typedef struct { BYTE B,G,R; } colorRGB;
|
||||
typedef struct { BYTE length; WORD value;} bitstring;
|
||||
|
||||
#define Y(R,G,B) ((BYTE)( (YRtab[(R)]+YGtab[(G)]+YBtab[(B)])>>16 ) - 128);
|
||||
#define Cb(R,G,B) ((BYTE)( (CbRtab[(R)]+CbGtab[(G)]+CbBtab[(B)])>>16 ));
|
||||
#define Cr(R,G,B) ((BYTE)( (CrRtab[(R)]+CrGtab[(G)]+CrBtab[(B)])>>16 ));
|
||||
|
||||
#define writebyte(b) fputc((b),fp_jpeg_stream);
|
||||
#define writebyte(b) fp_jpeg_stream->putchar(b);
|
||||
#define writeword(w) writebyte((w)/256);writebyte((w)%256);
|
||||
|
||||
struct APP0infotype
|
||||
@@ -252,12 +251,13 @@ class jpegenc
|
||||
SWORD DU_DCT[64];
|
||||
SWORD DU[64];
|
||||
|
||||
colorRGB *RGB_buffer; //image to be encoded
|
||||
BYTE *RGB_buffer; //image to be encoded
|
||||
WORD width, height; //image dimensions divisible by 8
|
||||
int pitch;
|
||||
|
||||
FILE *fp_jpeg_stream;
|
||||
|
||||
int encode(const char *filename, colorRGB *pixels, int iw, int ih, int jpegquality);
|
||||
stream *fp_jpeg_stream;
|
||||
|
||||
int encode(const char *filename, SDL_Surface *image, int jpegquality);
|
||||
};
|
||||
|
||||
BYTE jpegenc::zigzag[64] = {
|
||||
@@ -779,31 +779,26 @@ void jpegenc::load_data_units_from_RGB_buffer(WORD xpos, WORD ypos)
|
||||
{
|
||||
BYTE x, y;
|
||||
BYTE pos = 0;
|
||||
DWORD location, maxlocation;
|
||||
WORD width8, height8;
|
||||
BYTE R, G, B;
|
||||
location = ypos * width + xpos;
|
||||
maxlocation = width * height;
|
||||
width8 = width - xpos;
|
||||
height8 = height - ypos;
|
||||
BYTE R, G, B, *location0 = RGB_buffer + (ypos * pitch + xpos * 3);
|
||||
WORD width8 = width - xpos, height8 = height - ypos;
|
||||
for (y=0; y<8; y++)
|
||||
{
|
||||
BYTE *location = location0;
|
||||
for (x=0; x<8; x++)
|
||||
{
|
||||
if(location < maxlocation && x < width8 && y < height8)
|
||||
if(x < width8 && y < height8)
|
||||
{
|
||||
R = RGB_buffer[location].R;
|
||||
G = RGB_buffer[location].G;
|
||||
B = RGB_buffer[location].B;
|
||||
R = *location++;
|
||||
G = *location++;
|
||||
B = *location++;
|
||||
}
|
||||
else R = G = B = 0;
|
||||
YDU[pos] = Y(R,G,B);
|
||||
CbDU[pos] = Cb(R,G,B);
|
||||
CrDU[pos] = Cr(R,G,B);
|
||||
location++;
|
||||
pos++;
|
||||
}
|
||||
location += width - 8;
|
||||
location0 += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,13 +818,14 @@ void jpegenc::main_encoder()
|
||||
}
|
||||
}
|
||||
|
||||
int jpegenc::encode(const char *filename, colorRGB *pixels, int iw, int ih, int jpegquality)
|
||||
int jpegenc::encode(const char *filename, SDL_Surface *image, int jpegquality)
|
||||
{
|
||||
RGB_buffer = pixels;
|
||||
width = iw;
|
||||
height = ih;
|
||||
RGB_buffer = (BYTE *)image->pixels;
|
||||
width = image->w;
|
||||
height = image->h;
|
||||
pitch = image->pitch;
|
||||
|
||||
fp_jpeg_stream = fopen(filename,"wb");
|
||||
fp_jpeg_stream = openfile(filename,"wb");
|
||||
if(!fp_jpeg_stream)
|
||||
{
|
||||
return -1;
|
||||
@@ -868,10 +864,9 @@ int jpegenc::encode(const char *filename, colorRGB *pixels, int iw, int ih, int
|
||||
}
|
||||
writeword(0xFFD9);
|
||||
|
||||
//free(RGB_buffer);
|
||||
free(category_alloc);
|
||||
free(bitcode_alloc);
|
||||
fclose(fp_jpeg_stream);
|
||||
delete fp_jpeg_stream;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
+55
-171
@@ -164,136 +164,6 @@ void setprocesspriority(bool high)
|
||||
}
|
||||
#endif
|
||||
|
||||
FVARP(screenshotscale, 0.1f, 1.0f, 1.0f);
|
||||
|
||||
void bmp_screenshot(const char *imagepath, bool mapshot = false)
|
||||
{
|
||||
extern int minimaplastsize;
|
||||
int iw = mapshot?minimaplastsize:screen->w;
|
||||
int ih = mapshot?minimaplastsize:screen->h;
|
||||
int tw = mapshot ? iw : iw*screenshotscale;
|
||||
int th = mapshot ? ih : ih*screenshotscale;
|
||||
SDL_Surface *image = creatergbsurface(tw, th);
|
||||
if(!image) return;
|
||||
int tmpsize = iw * ih * 3;
|
||||
uchar *tmp = new uchar[tmpsize];
|
||||
uchar *dst = (uchar *)image->pixels;
|
||||
if(mapshot)
|
||||
{
|
||||
extern GLuint minimaptex;
|
||||
if(minimaptex)
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glBindTexture(GL_TEXTURE_2D, minimaptex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
conoutf("no mapshot prepared!");
|
||||
return;
|
||||
}
|
||||
loopi(th)
|
||||
{
|
||||
memcpy(dst, &tmp[3*tw*i], 3*tw);
|
||||
dst += image->pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
if(screenshotscale != 1.0f)
|
||||
{
|
||||
uchar *buf = new uchar[iw*ih*3];
|
||||
glReadPixels(0, 0, iw, ih, GL_RGB, GL_UNSIGNED_BYTE, buf); //screen->w//screen->h
|
||||
scaletexture(buf, iw, ih, 3, tmp, tw, th);
|
||||
delete[] buf;
|
||||
}
|
||||
else glReadPixels(0, 0, tw, th, GL_RGB, GL_UNSIGNED_BYTE, tmp);
|
||||
loopi(th)
|
||||
{
|
||||
memcpy(dst, &tmp[3*tw*(th-i-1)], 3*tw);
|
||||
dst += image->pitch;
|
||||
}
|
||||
}
|
||||
entropy_add_block(tmp, tmpsize);
|
||||
delete[] tmp;
|
||||
stream *file = openfile(imagepath, "wb");
|
||||
if(!file) conoutf("failed to create: %s", imagepath);
|
||||
else
|
||||
{
|
||||
SDL_SaveBMP_RW(image, file->rwops(), 1);
|
||||
delete file;
|
||||
}
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
|
||||
// best: 100 - good: 85 [default] - bad: 70 - terrible: 50
|
||||
VARP(jpegquality, 10, 85, 100);
|
||||
|
||||
#include "jpegenc.h"
|
||||
|
||||
void jpeg_screenshot(const char *imagepath, bool mapshot = false)
|
||||
{
|
||||
extern int minimaplastsize;
|
||||
int iw = mapshot?minimaplastsize:screen->w;
|
||||
int ih = mapshot?minimaplastsize:screen->h;
|
||||
int tw = mapshot ? iw : iw*screenshotscale;
|
||||
int th = mapshot ? ih : ih*screenshotscale;
|
||||
|
||||
int pixelssize = 3 * tw * th;
|
||||
uchar *pixels = new uchar[pixelssize];
|
||||
|
||||
if(mapshot)
|
||||
{
|
||||
extern GLuint minimaptex;
|
||||
if(minimaptex)
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glBindTexture(GL_TEXTURE_2D, minimaptex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGR, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
conoutf("no mapshot prepared!");
|
||||
delete[] pixels;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
if(screenshotscale != 1.0f)
|
||||
{
|
||||
uchar *buf = new uchar[iw*ih*3];
|
||||
glReadPixels(0, 0, iw, ih, GL_BGR, GL_UNSIGNED_BYTE, buf);
|
||||
scaletexture(buf, iw, ih, 3, pixels, tw, th);
|
||||
delete[] buf;
|
||||
}
|
||||
else glReadPixels(0, 0, tw, th, GL_BGR, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
int stride = 3*tw;
|
||||
|
||||
GLubyte *swapline = (GLubyte *) malloc(stride);
|
||||
for(int row = 0; row < th/2; row++)
|
||||
{
|
||||
memcpy(swapline, pixels + row * stride, stride);
|
||||
memcpy(pixels + row * stride, pixels + (th - row - 1) * stride, stride);
|
||||
memcpy(pixels + (th - row -1) * stride, swapline, stride);
|
||||
}
|
||||
free(swapline);
|
||||
}
|
||||
|
||||
const char *filename = findfile(imagepath, "wb");
|
||||
conoutf("writing to file: %s", filename);
|
||||
|
||||
jpegenc *jpegencoder = new jpegenc;
|
||||
jpegencoder->encode(filename, (colorRGB *)pixels, tw, th, jpegquality);
|
||||
delete jpegencoder;
|
||||
|
||||
entropy_add_block(pixels, pixelssize);
|
||||
delete[] pixels;
|
||||
}
|
||||
|
||||
VARP(pngcompress, 0, 9, 9);
|
||||
|
||||
void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0)
|
||||
@@ -396,20 +266,24 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void png_screenshot(const char *imagepath, bool mapshot = false)
|
||||
FVARP(screenshotscale, 0.1f, 1.0f, 1.0f);
|
||||
VARP(jpegquality, 10, 85, 100); // best: 100 - good: 85 [default] - bad: 70 - terrible: 50
|
||||
|
||||
#include "jpegenc.h"
|
||||
|
||||
void mapscreenshot(const char *imagepath, bool mapshot, int fileformat)
|
||||
{
|
||||
extern int minimaplastsize;
|
||||
int iw = mapshot?minimaplastsize:screen->w;
|
||||
int ih = mapshot?minimaplastsize:screen->h;
|
||||
int tw = mapshot ? iw : iw*screenshotscale;
|
||||
int th = mapshot ? ih : ih*screenshotscale;
|
||||
int src_w = mapshot ? minimaplastsize : screen->w;
|
||||
int src_h = mapshot ? minimaplastsize : screen->h;
|
||||
int dst_w = mapshot ? src_w : src_w * screenshotscale;
|
||||
int dst_h = mapshot ? src_h : src_h * screenshotscale;
|
||||
|
||||
SDL_Surface *image = creatergbsurface(tw, th);
|
||||
SDL_Surface *image = creatergbsurface(dst_w, dst_h);
|
||||
if(!image) return;
|
||||
|
||||
int tmpsize = tw * th * 3;
|
||||
uchar *tmp = new uchar[tmpsize];
|
||||
uchar *dst = (uchar *)image->pixels;
|
||||
int tmpdstsize = dst_w * dst_h * 3, dstpitch = dst_w * 3;
|
||||
uchar *tmpdst = new uchar[tmpdstsize], *dst = (uchar *)image->pixels;
|
||||
|
||||
if(mapshot)
|
||||
{
|
||||
@@ -418,40 +292,63 @@ void png_screenshot(const char *imagepath, bool mapshot = false)
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glBindTexture(GL_TEXTURE_2D, minimaptex);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tmp);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tmpdst);
|
||||
}
|
||||
else
|
||||
{
|
||||
conoutf("no mapshot prepared!");
|
||||
SDL_FreeSurface(image);
|
||||
return;
|
||||
}
|
||||
loopi(th)
|
||||
{
|
||||
memcpy(dst, &tmp[3*tw*i], 3*tw);
|
||||
loopi(dst_h)
|
||||
{ // copy image
|
||||
memcpy(dst, &tmpdst[dstpitch * i], dstpitch);
|
||||
dst += image->pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
if(screenshotscale != 1.0f)
|
||||
{
|
||||
uchar *buf = new uchar[iw*ih*3];
|
||||
glReadPixels(0, 0, iw, ih, GL_RGB, GL_UNSIGNED_BYTE, buf);
|
||||
scaletexture(buf, iw, ih, 3, tmp, tw, th);
|
||||
delete[] buf;
|
||||
if(src_w != dst_w || src_h != dst_h)
|
||||
{ // scale image
|
||||
uchar *tmpsrc = new uchar[src_w * src_h * 3];
|
||||
glReadPixels(0, 0, src_w, src_h, GL_RGB, GL_UNSIGNED_BYTE, tmpsrc);
|
||||
scaletexture(tmpsrc, src_w, src_h, 3, tmpdst, dst_w, dst_h);
|
||||
delete[] tmpsrc;
|
||||
}
|
||||
else glReadPixels(0, 0, tw, th, GL_RGB, GL_UNSIGNED_BYTE, tmp);
|
||||
loopi(th)
|
||||
{
|
||||
memcpy(dst, &tmp[3*tw*(th-i-1)], 3*tw);
|
||||
else glReadPixels(0, 0, dst_w, dst_h, GL_RGB, GL_UNSIGNED_BYTE, tmpdst);
|
||||
loopirev(dst_h)
|
||||
{ // flip image
|
||||
memcpy(dst, &tmpdst[dstpitch * i], dstpitch);
|
||||
dst += image->pitch;
|
||||
}
|
||||
}
|
||||
entropy_add_block(tmp, tmpsize);
|
||||
delete[] tmp;
|
||||
entropy_add_block(tmpdst, tmpdstsize);
|
||||
delete[] tmpdst;
|
||||
|
||||
if(save_png(imagepath, image) < 0) conoutf("\f3Error saving png file");
|
||||
switch(fileformat)
|
||||
{
|
||||
case 0: // bmp
|
||||
{
|
||||
stream *file = openfile(imagepath, "wb");
|
||||
if(!file) conoutf("failed to create: %s", imagepath);
|
||||
else
|
||||
{
|
||||
SDL_SaveBMP_RW(image, file->rwops(), 1);
|
||||
delete file;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: // jpeg
|
||||
{
|
||||
jpegenc jpegencoder;
|
||||
jpegencoder.encode(imagepath, image, jpegquality);
|
||||
break;
|
||||
}
|
||||
case 2: // png
|
||||
if(save_png(imagepath, image) < 0) conoutf("\f3Error saving png file");
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
@@ -472,27 +369,14 @@ void screenshot(const char *filename)
|
||||
else if(getclientmap()[0]) formatstring(buf)("screenshots/%s_%s_%s%s", timestring(), behindpath(getclientmap()), modestr(gamemode, true), getscrext());
|
||||
else formatstring(buf)("screenshots/%s%s", timestring(), getscrext());
|
||||
path(buf);
|
||||
|
||||
switch(screenshottype)
|
||||
{
|
||||
case 2: png_screenshot(buf, false); break;
|
||||
case 1: jpeg_screenshot(buf, false); break;
|
||||
case 0:
|
||||
default: bmp_screenshot(buf, false); break;
|
||||
}
|
||||
mapscreenshot(buf, false, screenshottype);
|
||||
}
|
||||
COMMAND(screenshot, "s");
|
||||
|
||||
void mapshot()
|
||||
{
|
||||
defformatstring(buf)("screenshots" PATHDIVS "mapshot_%s_%s%s", behindpath(getclientmap()), timestring(), getscrext());
|
||||
switch(screenshottype)
|
||||
{
|
||||
case 2: png_screenshot(buf,true); break;
|
||||
case 1: jpeg_screenshot(buf,true); break;
|
||||
case 0:
|
||||
default: bmp_screenshot(buf,true); break;
|
||||
}
|
||||
mapscreenshot(buf, true, screenshottype);
|
||||
}
|
||||
COMMAND(mapshot, "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user