# HG changeset patch # User sheepluva # Date 1418853703 -3600 # Node ID a88647ead05c592d779dd7f2d6089f840857eb51 # Parent 97f45f1374be9806225f9b46bafe4cc108f736ae don't save alpha channel to screenshots when not needed diff -r 97f45f1374be -r a88647ead05c hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Wed Dec 17 21:01:44 2014 +0100 +++ b/hedgewars/uMisc.pas Wed Dec 17 23:01:43 2014 +0100 @@ -46,6 +46,7 @@ filename: shortstring; width, height: LongInt; size: QWord; + alpha: boolean; end; var conversionFormat : PSDL_PixelFormat; @@ -69,8 +70,20 @@ info_ptr: ^png_info; f: File; image: PScreenshot; + bpp: Integer; // bytes per pixel + ctype: Integer; // png color type begin image:= PScreenshot(screenshot); +if image^.alpha then + begin + bpp:= 4; + ctype:= PNG_COLOR_TYPE_RGBA; + end +else + begin + bpp:= 3; + ctype:= PNG_COLOR_TYPE_RGB; + end; png_ptr := png_create_write_struct(png_get_libpng_ver(nil), nil, nil, nil); if png_ptr = nil then @@ -97,12 +110,12 @@ png_init_pascal_io(png_ptr,@f); png_set_IHDR(png_ptr, info_ptr, image^.width, image^.height, 8, // bit depth - PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, + ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); // glReadPixels and libpng number rows in different order for i:= image^.height-1 downto 0 do - png_write_row(png_ptr, image^.buffer + i*4*image^.width); + png_write_row(png_ptr, image^.buffer + i*bpp*image^.width); png_write_end(png_ptr, info_ptr); Close(f); end; @@ -130,7 +143,7 @@ 0, 0, 0, 0, // width 0, 0, 0, 0, // height 1, 0, // color planes - 32, 0, // bit depth + 24, 0, // bit depth 0, 0, 0, 0, // compression method (uncompressed) 0, 0, 0, 0, // image size 96, 0, 0, 0, // horizontal resolution @@ -163,6 +176,9 @@ head[$24]:= (size shr 16) and $ff; head[$25]:= (size shr 24) and $ff; +if image^.alpha then + head[$1C]:= 32; + {$IOCHECKS OFF} Assign(f, image^.filename); Rewrite(f, 1); @@ -188,8 +204,8 @@ {$IFDEF USE_VIDEO_RECORDING} // make image k times smaller (useful for saving thumbnails) -procedure ReduceImage(img: PByte; width, height, k: LongInt); -var i, j, i0, j0, w, h, r, g, b: LongInt; +procedure ReduceImage(img: PByte; width, height, k: LongInt; bpp: Integer); + var i, j, i0, j0, w, h, r, g, b, off, ksqr: LongInt; begin w:= width div k; h:= height div k; @@ -197,6 +213,7 @@ // rescale inplace if k <> 1 then begin + ksqr:= k*k; for i:= 0 to h-1 do for j:= 0 to w-1 do begin @@ -206,14 +223,21 @@ for i0:= 0 to k-1 do for j0:= 0 to k-1 do begin - inc(r, img[4*(width*(i*k+i0) + j*k+j0)+0]); - inc(g, img[4*(width*(i*k+i0) + j*k+j0)+1]); - inc(b, img[4*(width*(i*k+i0) + j*k+j0)+2]); + off:= bpp*(width*(i*k+i0) + j*k+j0); + inc(r, img[off]); inc(off); + inc(g, img[off]); inc(off); + inc(b, img[off]); end; - img[4*(w*i + j)+0]:= r div (k*k); - img[4*(w*i + j)+1]:= g div (k*k); - img[4*(w*i + j)+2]:= b div (k*k); - img[4*(w*i + j)+3]:= 255; + off:= bpp*(w*i + j); + img[off]:= r div (ksqr); inc(off); + img[off]:= g div (ksqr); inc(off); + img[off]:= b div (ksqr); + // if there's an alpha channel set opacity to max + if bpp > 3 then + begin + inc(off); + img[off]:= 255; + end; end; end; end; @@ -228,18 +252,33 @@ format: GLenum; ext: string[4]; x,y: LongWord; + hasA: boolean; + bpp: Integer; begin +hasA:= (dump > 0); + +if hasA then + bpp:= 4 +else + bpp:= 3; + {$IFDEF PNG_SCREENSHOTS} -format:= GL_RGBA; +if hasA then + format:= GL_RGBA +else + format:= GL_RGB; ext:= '.png'; {$ELSE} -format:= GL_BGRA; +if hasA then + format:= GL_BGRA +else + format:= GL_BGR; ext:= '.bmp'; {$ENDIF} if dump > 0 then - size:= LAND_WIDTH*LAND_HEIGHT*4 -else size:= toPowerOf2(cScreenWidth) * toPowerOf2(cScreenHeight) * 4; + size:= LAND_WIDTH*LAND_HEIGHT*bpp +else size:= toPowerOf2(cScreenWidth) * toPowerOf2(cScreenHeight) * bpp; p:= GetMem(size); // will be freed in SaveScreenshot() // memory could not be allocated @@ -277,7 +316,7 @@ begin glReadPixels(0, 0, cScreenWidth, cScreenHeight, format, GL_UNSIGNED_BYTE, p); {$IFDEF USE_VIDEO_RECORDING} - ReduceImage(p, cScreenWidth, cScreenHeight, k) + ReduceImage(p, cScreenWidth, cScreenHeight, k, bpp) {$ENDIF} end; @@ -301,6 +340,7 @@ end; image^.size:= size; image^.buffer:= p; +image^.alpha:= hasA; SDL_CreateThread(@SaveScreenshot{$IFDEF SDL2}, 'snapshot'{$ENDIF}, image); MakeScreenshot:= true; // possibly it is not true but we will not wait for thread to terminate