/* ================== RB_TakeScreenshotPNG ================== */ static void RB_TakeScreenshotPNG(int x, int y, int width, int height, char *fileName) { byte *buffer; size_t offset = 0, memcount; int padlen; buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen); memcount = (width * 3 + padlen) * height; // gamma correct if(glConfig.deviceSupportsGamma) R_GammaCorrect(buffer + offset, memcount); RE_SavePNG(fileName, width, height, buffer+offset, 3, padlen, qfalse); ri.Hunk_FreeTempMemory(buffer); }
/* ==================== R_LevelShot levelshots are specialized 128*128 thumbnails for the menu system, sampled down from full screen distorted images ==================== */ void R_LevelShot( screenshotType_e type, const char *ext ) { char fileName[MAX_OSPATH]; byte *source; byte *resample, *resamplestart; size_t offset = 0, memcount; int spadlen, rpadlen; int padwidth, linelen; GLint packAlign; byte *src, *dst; int x, y; int r, g, b; float xScale, yScale; int xx, yy; int width, height; int arg; // Allow custom resample width/height arg = atoi(ri.Cmd_Argv(2)); if (arg > 0) width = height = arg; else width = height = 128; if (width > glConfig.vidWidth) width = glConfig.vidWidth; if (height > glConfig.vidHeight) height = glConfig.vidHeight; Com_sprintf(fileName, sizeof(fileName), "levelshots/%s_small%s", tr.world->baseName, ext); source = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &spadlen); // // Based on RB_ReadPixels qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); linelen = width * 3; padwidth = PAD(linelen, packAlign); // Allocate a few more bytes so that we can choose an alignment we like resample = ri.Hunk_AllocateTempMemory(padwidth * height + offset + packAlign - 1); resamplestart = PADP((intptr_t) resample + offset, packAlign); offset = resamplestart - resample; rpadlen = padwidth - linelen; // // resample from source xScale = glConfig.vidWidth / (float)(width * 4.0f); yScale = glConfig.vidHeight / (float)(height * 3.0f); for ( y = 0 ; y < height ; y++ ) { for ( x = 0 ; x < width ; x++ ) { r = g = b = 0; for ( yy = 0 ; yy < 3 ; yy++ ) { for ( xx = 0 ; xx < 4 ; xx++ ) { src = source + (3 * glConfig.vidWidth + spadlen) * (int)((y*3 + yy) * yScale) + 3 * (int) ((x*4 + xx) * xScale); r += src[0]; g += src[1]; b += src[2]; } } dst = resample + 3 * ( y * width + x ); dst[0] = r / 12; dst[1] = g / 12; dst[2] = b / 12; } } memcount = (width * 3 + rpadlen) * height; // gamma correct if(glConfig.deviceSupportsGamma) R_GammaCorrect(resample + offset, memcount); if ( type == ST_TGA ) RE_SaveTGA(fileName, width, height, resample + offset, rpadlen); else if ( type == ST_JPEG ) RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, resample + offset, rpadlen); else if ( type == ST_PNG ) RE_SavePNG(fileName, width, height, resample + offset, rpadlen); ri.Hunk_FreeTempMemory(resample); ri.Hunk_FreeTempMemory(source); ri.Printf( PRINT_ALL, "Wrote %s\n", fileName ); }