diff --git a/source/src/jpegenc.h b/source/src/jpegenc.h index dbf881ba..d7b1e315 100644 --- a/source/src/jpegenc.h +++ b/source/src/jpegenc.h @@ -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; }; diff --git a/source/src/main.cpp b/source/src/main.cpp index 2978b3b3..d18706fa 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -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, "");