mirror of
https://github.com/ioquake/ioq3.git
synced 2025-05-30 00:20:59 +00:00
Merge af7812f1a0
into 10afd421f2
This commit is contained in:
commit
a69ed7f470
14 changed files with 4208 additions and 243 deletions
3
Makefile
3
Makefile
|
@ -2368,10 +2368,13 @@ endif
|
|||
ifeq ($(USE_INTERNAL_ZLIB),1)
|
||||
Q3OBJ += \
|
||||
$(B)/client/adler32.o \
|
||||
$(B)/client/compress.o \
|
||||
$(B)/client/crc32.o \
|
||||
$(B)/client/deflate.o \
|
||||
$(B)/client/inffast.o \
|
||||
$(B)/client/inflate.o \
|
||||
$(B)/client/inftrees.o \
|
||||
$(B)/client/trees.o \
|
||||
$(B)/client/zutil.o
|
||||
endif
|
||||
|
||||
|
|
|
@ -3193,6 +3193,28 @@ int CL_ScaledMilliseconds(void) {
|
|||
return Sys_Milliseconds()*com_timescale->value;
|
||||
}
|
||||
|
||||
void CL_GetModDescription( char *buf, int bufLength ) {
|
||||
FS_GetModDescription( FS_GetCurrentGameDir(), buf, bufLength );
|
||||
}
|
||||
|
||||
void CL_GetMapTitle( char *buf, int bufLength ) {
|
||||
Q_strncpyz(buf, cl.gameState.stringData + cl.gameState.stringOffsets[CS_MESSAGE], bufLength);
|
||||
}
|
||||
|
||||
void CL_GetPlayerLocation( char *buf, int bufLength ) {
|
||||
playerState_t *ps;
|
||||
|
||||
if (clc.state != CA_ACTIVE || !cl.snap.valid) {
|
||||
Q_strncpyz(buf, "Unknown", bufLength);
|
||||
return;
|
||||
}
|
||||
|
||||
ps = &cl.snap.ps;
|
||||
Com_sprintf(buf, bufLength, "X:%d Y:%d Z:%d A:%d", (int)ps->origin[0],
|
||||
(int)ps->origin[1], (int)ps->origin[2],
|
||||
(int)(ps->viewangles[YAW]+360)%360);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CL_InitRef
|
||||
|
@ -3269,6 +3291,7 @@ void CL_InitRef( void ) {
|
|||
ri.Cvar_CheckRange = Cvar_CheckRange;
|
||||
ri.Cvar_SetDescription = Cvar_SetDescription;
|
||||
ri.Cvar_VariableIntegerValue = Cvar_VariableIntegerValue;
|
||||
ri.Cvar_VariableStringBuffer = Cvar_VariableStringBuffer;
|
||||
|
||||
// cinematic stuff
|
||||
|
||||
|
@ -3289,6 +3312,13 @@ void CL_InitRef( void ) {
|
|||
ri.Sys_GLimpInit = Sys_GLimpInit;
|
||||
ri.Sys_LowPhysicalMemory = Sys_LowPhysicalMemory;
|
||||
|
||||
ri.zlib_compress = compress;
|
||||
ri.zlib_crc32 = crc32;
|
||||
|
||||
ri.CL_GetModDescription = CL_GetModDescription;
|
||||
ri.CL_GetMapTitle = CL_GetMapTitle;
|
||||
ri.CL_GetPlayerLocation = CL_GetPlayerLocation;
|
||||
|
||||
ret = GetRefAPI( REF_API_VERSION, &ri );
|
||||
|
||||
#if defined __USEA3D && defined __A3D_GEOM
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
===========================================================================
|
||||
ioquake3 png decoder
|
||||
ioquake3 png decoder and encoder
|
||||
Copyright (C) 2007,2008 Joerg Dietrich
|
||||
Copyright (C) 2011 Zack Middleton
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -78,6 +79,7 @@ typedef uint32_t PNG_ChunkCRC;
|
|||
#define MAKE_CHUNKTYPE(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d)))
|
||||
|
||||
#define PNG_ChunkType_IHDR MAKE_CHUNKTYPE('I', 'H', 'D', 'R')
|
||||
#define PNG_ChunkType_tEXt MAKE_CHUNKTYPE('t', 'E', 'X', 't')
|
||||
#define PNG_ChunkType_PLTE MAKE_CHUNKTYPE('P', 'L', 'T', 'E')
|
||||
#define PNG_ChunkType_IDAT MAKE_CHUNKTYPE('I', 'D', 'A', 'T')
|
||||
#define PNG_ChunkType_IEND MAKE_CHUNKTYPE('I', 'E', 'N', 'D')
|
||||
|
@ -2483,3 +2485,296 @@ void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
|
|||
|
||||
CloseBufferedFile(ThePNG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a non-interlaced 8-bit true color image
|
||||
*/
|
||||
|
||||
static qboolean EncodeImageNonInterlaced8True(uint32_t IHDR_Width, uint32_t IHDR_Height,
|
||||
byte *InBuffer,
|
||||
uint32_t InBytesPerPixel,
|
||||
uint32_t Padding,
|
||||
uint8_t *ImageData)
|
||||
{
|
||||
uint32_t BytesPerScanline, BytesPerPixel, PixelsPerByte;
|
||||
uint32_t w, h;
|
||||
byte *InPtr;
|
||||
uint8_t *OutPtr;
|
||||
|
||||
/*
|
||||
* input verification
|
||||
*/
|
||||
|
||||
if(!InBuffer)
|
||||
{
|
||||
return(qfalse);
|
||||
}
|
||||
|
||||
/*
|
||||
* information for un-filtering
|
||||
* PNG_ColourType_True, PNG_BitDepth_8
|
||||
*/
|
||||
|
||||
BytesPerPixel = PNG_NumColourComponents_True;
|
||||
PixelsPerByte = 1;
|
||||
|
||||
/*
|
||||
* Calculate the size of one scanline
|
||||
*/
|
||||
|
||||
BytesPerScanline = (IHDR_Width * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
|
||||
|
||||
/*
|
||||
* Set the working pointers to the beginning of the buffers.
|
||||
*/
|
||||
|
||||
InPtr = InBuffer;
|
||||
OutPtr = ImageData;
|
||||
|
||||
/*
|
||||
* Create the output image.
|
||||
*/
|
||||
|
||||
for(h = IHDR_Height; h > 0; h--)
|
||||
{
|
||||
InPtr = InBuffer + (BytesPerScanline + Padding) * (h - 1);
|
||||
|
||||
/*
|
||||
* set FilterType
|
||||
*/
|
||||
|
||||
OutPtr[0] = PNG_FilterType_None;
|
||||
OutPtr++;
|
||||
|
||||
for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
|
||||
{
|
||||
OutPtr[0] = InPtr[0];
|
||||
OutPtr[1] = InPtr[1];
|
||||
OutPtr[2] = InPtr[2];
|
||||
|
||||
InPtr += InBytesPerPixel;
|
||||
OutPtr += BytesPerPixel;
|
||||
}
|
||||
}
|
||||
|
||||
return(qtrue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to buffer.
|
||||
*/
|
||||
|
||||
void WriteToBuffer(void **buffer, const void *data, size_t length)
|
||||
{
|
||||
memcpy(*buffer, data, length);
|
||||
*(byte**)buffer += length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write PNG chuck header to buffer.
|
||||
*/
|
||||
|
||||
void WriteChunkHeader(void **buffer, void **crcPtr, PNG_ChunkCRC *CRC, int type, int length)
|
||||
{
|
||||
struct PNG_ChunkHeader CH;
|
||||
|
||||
/*
|
||||
* Write chuck header
|
||||
*/
|
||||
|
||||
CH.Type = BigLong(type);
|
||||
CH.Length = BigLong(length);
|
||||
|
||||
WriteToBuffer(buffer, &CH, PNG_ChunkHeader_Size);
|
||||
|
||||
/*
|
||||
* Init CRC
|
||||
*/
|
||||
|
||||
*CRC = ri.zlib_crc32(0, Z_NULL, 0);
|
||||
*CRC = ri.zlib_crc32(*CRC, *(byte**)buffer-4, 4);
|
||||
*crcPtr = *buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write CRC to buffer.
|
||||
*/
|
||||
|
||||
void WriteCRC(void **buffer, void **crcPtr, PNG_ChunkCRC CRC)
|
||||
{
|
||||
int size = (intptr_t)*buffer-(intptr_t)*crcPtr;
|
||||
|
||||
/*
|
||||
* Update CRC
|
||||
*/
|
||||
if (size > 0)
|
||||
CRC = ri.zlib_crc32(CRC, *crcPtr, size);
|
||||
|
||||
/*
|
||||
* Write CRC
|
||||
*/
|
||||
CRC = BigLong(CRC);
|
||||
WriteToBuffer(buffer, &CRC, PNG_ChunkCRC_Size);
|
||||
}
|
||||
|
||||
/*
|
||||
* The PNG saver
|
||||
*/
|
||||
|
||||
void RE_SavePNG(const char *filename, int width, int height, byte *data, int padding) {
|
||||
void *pngData;
|
||||
size_t pngSize;
|
||||
void *buffer;
|
||||
struct PNG_Chunk_IHDR IHDR;
|
||||
PNG_ChunkCRC CRC;
|
||||
void *crcPtr;
|
||||
int numtEXt = 0;
|
||||
#define NUMTEXT 7
|
||||
struct
|
||||
{
|
||||
char key[80]; // PNG limits to 79+'\0'.
|
||||
char text[256]; // PNG allows any length.
|
||||
} tEXt[NUMTEXT];
|
||||
int i;
|
||||
uint8_t *imageData;
|
||||
uint32_t imageLength;
|
||||
Bytef *compressedData = NULL;
|
||||
uLongf compressedDataLength;
|
||||
|
||||
/*
|
||||
* Create the png image data from buffer.
|
||||
*/
|
||||
|
||||
imageLength = (width*PNG_NumColourComponents_True + 1) * height;
|
||||
imageData = ri.Malloc(imageLength);
|
||||
|
||||
EncodeImageNonInterlaced8True(width, height, data, 3, padding, imageData);
|
||||
|
||||
/*
|
||||
* Compress the png image data.
|
||||
*/
|
||||
|
||||
compressedDataLength = imageLength * 1.01f + 12;
|
||||
compressedData = ri.Malloc(compressedDataLength);
|
||||
|
||||
if (ri.zlib_compress(compressedData, &compressedDataLength, imageData, imageLength) != Z_OK) {
|
||||
ri.Free(compressedData);
|
||||
ri.Free(imageData);
|
||||
ri.Printf(PRINT_WARNING, "RE_SavePNG: Failed to compress image data.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup text data.
|
||||
*/
|
||||
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Title", sizeof (tEXt[numtEXt].key));
|
||||
ri.Cvar_VariableStringBuffer("version", tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Author", sizeof (tEXt[numtEXt].key));
|
||||
ri.Cvar_VariableStringBuffer("username", tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Description", sizeof (tEXt[numtEXt].key));
|
||||
ri.CL_GetModDescription(tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Mapname", sizeof (tEXt[numtEXt].key));
|
||||
ri.Cvar_VariableStringBuffer("mapname", tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Maptitle", sizeof (tEXt[numtEXt].key));
|
||||
ri.CL_GetMapTitle(tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Playername", sizeof (tEXt[numtEXt].key));
|
||||
ri.Cvar_VariableStringBuffer("name", tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
Q_strncpyz(tEXt[numtEXt].key, "Location", sizeof (tEXt[numtEXt].key));
|
||||
ri.CL_GetPlayerLocation(tEXt[numtEXt].text, sizeof (tEXt[numtEXt].text));
|
||||
numtEXt++;
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the size of the image.
|
||||
*/
|
||||
|
||||
pngSize = PNG_Signature_Size + PNG_ChunkHeader_Size + PNG_Chunk_IHDR_Size + PNG_ChunkCRC_Size;
|
||||
|
||||
/*
|
||||
* Calculate the length of the tEXt chunks.
|
||||
*/
|
||||
|
||||
for (i = 0; i < numtEXt; i++) {
|
||||
pngSize += PNG_ChunkHeader_Size + strlen(tEXt[i].key)+1 + strlen(tEXt[i].text) + PNG_ChunkCRC_Size;
|
||||
}
|
||||
|
||||
pngSize += PNG_ChunkHeader_Size + compressedDataLength + PNG_ChunkCRC_Size
|
||||
+ PNG_ChunkHeader_Size + PNG_ChunkCRC_Size;
|
||||
|
||||
/*
|
||||
* Allocate memory to hold the full png image data.
|
||||
*/
|
||||
|
||||
buffer = pngData = ri.Hunk_AllocateTempMemory(pngSize);
|
||||
|
||||
/*
|
||||
* Setup CRC.
|
||||
*/
|
||||
|
||||
CRC = ri.zlib_crc32(0, Z_NULL, 0);
|
||||
crcPtr = (byte*)buffer + PNG_Signature_Size + 4;
|
||||
|
||||
/*
|
||||
* Header
|
||||
*/
|
||||
|
||||
WriteToBuffer(&buffer, PNG_Signature, PNG_Signature_Size);
|
||||
|
||||
WriteChunkHeader(&buffer, &crcPtr, &CRC, PNG_ChunkType_IHDR, PNG_Chunk_IHDR_Size);
|
||||
IHDR.Width = BigLong(width);
|
||||
IHDR.Height = BigLong(height);
|
||||
IHDR.BitDepth = PNG_BitDepth_8;
|
||||
IHDR.ColourType = PNG_ColourType_True;
|
||||
IHDR.CompressionMethod = PNG_CompressionMethod_0;
|
||||
IHDR.FilterMethod = PNG_FilterMethod_0;
|
||||
IHDR.InterlaceMethod = PNG_InterlaceMethod_NonInterlaced;
|
||||
WriteToBuffer(&buffer, &IHDR, PNG_Chunk_IHDR_Size);
|
||||
WriteCRC(&buffer, &crcPtr, CRC);
|
||||
|
||||
/*
|
||||
* tEXt, Textual data.
|
||||
*/
|
||||
for (i = 0; i < numtEXt; i++) {
|
||||
WriteChunkHeader(&buffer, &crcPtr, &CRC, PNG_ChunkType_tEXt, strlen(tEXt[i].key)+1 + strlen(tEXt[i].text));
|
||||
|
||||
/*
|
||||
* Write string data.
|
||||
*/
|
||||
WriteToBuffer(&buffer, tEXt[i].key, strlen(tEXt[i].key)+1);
|
||||
WriteToBuffer(&buffer, tEXt[i].text, strlen(tEXt[i].text));
|
||||
|
||||
WriteCRC(&buffer, &crcPtr, CRC);
|
||||
}
|
||||
|
||||
/*
|
||||
* IDAT, Image Data.
|
||||
*/
|
||||
WriteChunkHeader(&buffer, &crcPtr, &CRC, PNG_ChunkType_IDAT, compressedDataLength);
|
||||
WriteToBuffer(&buffer, compressedData, compressedDataLength);
|
||||
WriteCRC(&buffer, &crcPtr, CRC);
|
||||
|
||||
/*
|
||||
* IEND, Image End.
|
||||
*/
|
||||
WriteChunkHeader(&buffer, &crcPtr, &CRC, PNG_ChunkType_IEND, 0);
|
||||
WriteCRC(&buffer, &crcPtr, CRC);
|
||||
|
||||
/*
|
||||
* Write the image to file.
|
||||
*/
|
||||
ri.FS_WriteFile(filename, pngData, pngSize);
|
||||
|
||||
/*
|
||||
* Free memory.
|
||||
*/
|
||||
ri.Hunk_FreeTempMemory(pngData);
|
||||
ri.Free(compressedData);
|
||||
ri.Free(imageData);
|
||||
}
|
||||
|
|
|
@ -313,3 +313,50 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
|||
|
||||
ri.FS_FreeFile (buffer.v);
|
||||
}
|
||||
|
||||
void RE_SaveTGA(char * filename, int image_width, int image_height, byte *image_buffer, int padding) {
|
||||
byte *srcptr, *destptr;
|
||||
byte *endline, *endmem;
|
||||
byte *out;
|
||||
size_t bufSize;
|
||||
int linelen;
|
||||
|
||||
bufSize = image_width * image_height * 3 + 18;
|
||||
out = ri.Hunk_AllocateTempMemory(bufSize);
|
||||
|
||||
Com_Memset (out, 0, 18);
|
||||
out[2] = 2; // uncompressed type
|
||||
out[12] = image_width & 255;
|
||||
out[13] = image_width >> 8;
|
||||
out[14] = image_height & 255;
|
||||
out[15] = image_height >> 8;
|
||||
out[16] = 24; // pixel size
|
||||
|
||||
// swap rgb to bgr and remove padding from line endings
|
||||
linelen = image_width * 3;
|
||||
|
||||
srcptr = image_buffer;
|
||||
destptr = out + 18;
|
||||
endmem = srcptr + (linelen + padding) * image_height;
|
||||
|
||||
while(srcptr < endmem)
|
||||
{
|
||||
endline = srcptr + linelen;
|
||||
|
||||
while(srcptr < endline)
|
||||
{
|
||||
*destptr++ = srcptr[2];
|
||||
*destptr++ = srcptr[1];
|
||||
*destptr++ = srcptr[0];
|
||||
|
||||
srcptr += 3;
|
||||
}
|
||||
|
||||
// Skip the pad
|
||||
srcptr += padding;
|
||||
}
|
||||
|
||||
ri.FS_WriteFile(filename, out, bufSize);
|
||||
|
||||
ri.Hunk_FreeTempMemory(out);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#include "tr_types.h"
|
||||
|
||||
#ifdef USE_LOCAL_HEADERS
|
||||
#include "../zlib/zlib.h"
|
||||
#else
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#define REF_API_VERSION 8
|
||||
|
||||
//
|
||||
|
@ -180,6 +186,17 @@ typedef struct {
|
|||
void (*Sys_GLimpSafeInit)( void );
|
||||
void (*Sys_GLimpInit)( void );
|
||||
qboolean (*Sys_LowPhysicalMemory)( void );
|
||||
|
||||
void (*Cvar_VariableStringBuffer) (const char *var_name, char *buffer, int bufsize);
|
||||
|
||||
// zlib for png screenshots
|
||||
int (*zlib_compress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
|
||||
uLong (*zlib_crc32) (uLong crc, const Bytef *buf, uInt len);
|
||||
|
||||
// get extra info for png screenshots
|
||||
void (*CL_GetModDescription)( char *buf, int bufLength );
|
||||
void (*CL_GetMapTitle)( char *buf, int bufLength );
|
||||
void (*CL_GetPlayerLocation)( char *buf, int bufLength );
|
||||
} refimport_t;
|
||||
|
||||
|
||||
|
|
|
@ -387,63 +387,24 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa
|
|||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshot
|
||||
RB_TakeScreenshotTGA
|
||||
==================
|
||||
*/
|
||||
void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
|
||||
void RB_TakeScreenshotTGA(int x, int y, int width, int height, char *fileName)
|
||||
{
|
||||
byte *allbuf, *buffer;
|
||||
byte *srcptr, *destptr;
|
||||
byte *endline, *endmem;
|
||||
byte temp;
|
||||
|
||||
int linelen, padlen;
|
||||
size_t offset = 18, memcount;
|
||||
|
||||
allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
|
||||
buffer = allbuf + offset - 18;
|
||||
|
||||
Com_Memset (buffer, 0, 18);
|
||||
buffer[2] = 2; // uncompressed type
|
||||
buffer[12] = width & 255;
|
||||
buffer[13] = width >> 8;
|
||||
buffer[14] = height & 255;
|
||||
buffer[15] = height >> 8;
|
||||
buffer[16] = 24; // pixel size
|
||||
byte *buffer;
|
||||
size_t offset = 0, memcount;
|
||||
int padlen;
|
||||
|
||||
// swap rgb to bgr and remove padding from line endings
|
||||
linelen = width * 3;
|
||||
|
||||
srcptr = destptr = allbuf + offset;
|
||||
endmem = srcptr + (linelen + padlen) * height;
|
||||
|
||||
while(srcptr < endmem)
|
||||
{
|
||||
endline = srcptr + linelen;
|
||||
|
||||
while(srcptr < endline)
|
||||
{
|
||||
temp = srcptr[0];
|
||||
*destptr++ = srcptr[2];
|
||||
*destptr++ = srcptr[1];
|
||||
*destptr++ = temp;
|
||||
|
||||
srcptr += 3;
|
||||
}
|
||||
|
||||
// Skip the pad
|
||||
srcptr += padlen;
|
||||
}
|
||||
|
||||
memcount = linelen * height;
|
||||
buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen);
|
||||
memcount = (width * 3 + padlen) * height;
|
||||
|
||||
// gamma correct
|
||||
if(glConfig.deviceSupportsGamma)
|
||||
R_GammaCorrect(allbuf + offset, memcount);
|
||||
R_GammaCorrect(buffer + offset, memcount);
|
||||
|
||||
ri.FS_WriteFile(fileName, buffer, memcount + 18);
|
||||
|
||||
ri.Hunk_FreeTempMemory(allbuf);
|
||||
RE_SaveTGA(fileName, width, height, buffer + offset, padlen);
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -469,6 +430,28 @@ void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
|
|||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshotPNG
|
||||
==================
|
||||
*/
|
||||
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, padlen);
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshotCmd
|
||||
|
@ -479,10 +462,12 @@ const void *RB_TakeScreenshotCmd( const void *data ) {
|
|||
|
||||
cmd = (const screenshotCommand_t *)data;
|
||||
|
||||
if (cmd->jpeg)
|
||||
RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
||||
else
|
||||
RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
||||
if (cmd->type == ST_TGA)
|
||||
RB_TakeScreenshotTGA( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
else if (cmd->type == ST_JPEG)
|
||||
RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
else if (cmd->type == ST_PNG)
|
||||
RB_TakeScreenshotPNG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
|
||||
return (const void *)(cmd + 1);
|
||||
}
|
||||
|
@ -492,7 +477,7 @@ const void *RB_TakeScreenshotCmd( const void *data ) {
|
|||
R_TakeScreenshot
|
||||
==================
|
||||
*/
|
||||
void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
|
||||
void R_TakeScreenshot( int x, int y, int width, int height, char *name, screenshotType_e type ) {
|
||||
static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
|
||||
screenshotCommand_t *cmd;
|
||||
|
||||
|
@ -508,7 +493,7 @@ void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean
|
|||
cmd->height = height;
|
||||
Q_strncpyz( fileName, name, sizeof(fileName) );
|
||||
cmd->fileName = fileName;
|
||||
cmd->jpeg = jpeg;
|
||||
cmd->type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -516,11 +501,11 @@ void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean
|
|||
R_ScreenshotFilename
|
||||
==================
|
||||
*/
|
||||
void R_ScreenshotFilename( int lastNumber, char *fileName ) {
|
||||
void R_ScreenshotFilename( int lastNumber, char *fileName, char *ext ) {
|
||||
int a,b,c,d;
|
||||
|
||||
if ( lastNumber < 0 || lastNumber > 9999 ) {
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999%s", ext );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -532,33 +517,8 @@ void R_ScreenshotFilename( int lastNumber, char *fileName ) {
|
|||
lastNumber -= c*10;
|
||||
d = lastNumber;
|
||||
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
|
||||
, a, b, c, d );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ScreenshotFilename
|
||||
==================
|
||||
*/
|
||||
void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
|
||||
int a,b,c,d;
|
||||
|
||||
if ( lastNumber < 0 || lastNumber > 9999 ) {
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
|
||||
return;
|
||||
}
|
||||
|
||||
a = lastNumber / 1000;
|
||||
lastNumber -= a*1000;
|
||||
b = lastNumber / 100;
|
||||
lastNumber -= b*100;
|
||||
c = lastNumber / 10;
|
||||
lastNumber -= c*10;
|
||||
d = lastNumber;
|
||||
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
|
||||
, a, b, c, d );
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i%s"
|
||||
, a, b, c, d, ext );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -569,63 +529,80 @@ levelshots are specialized 128*128 thumbnails for
|
|||
the menu system, sampled down from full screen distorted images
|
||||
====================
|
||||
*/
|
||||
void R_LevelShot( void ) {
|
||||
char checkname[MAX_OSPATH];
|
||||
byte *buffer;
|
||||
void R_LevelShot( screenshotType_e type, const char *ext ) {
|
||||
char fileName[MAX_OSPATH];
|
||||
byte *source, *allsource;
|
||||
byte *resample;
|
||||
size_t offset = 0, memcount;
|
||||
int spadlen;
|
||||
int linelen;
|
||||
byte *src, *dst;
|
||||
size_t offset = 0;
|
||||
int padlen;
|
||||
int x, y;
|
||||
int r, g, b;
|
||||
float xScale, yScale;
|
||||
int xx, yy;
|
||||
int width, height;
|
||||
int arg;
|
||||
|
||||
Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName);
|
||||
// Allow custom resample width/height
|
||||
arg = atoi(ri.Cmd_Argv(2));
|
||||
if (arg > 0)
|
||||
width = height = arg;
|
||||
else
|
||||
width = height = 128;
|
||||
|
||||
allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen);
|
||||
if (width > glConfig.vidWidth)
|
||||
width = glConfig.vidWidth;
|
||||
if (height > glConfig.vidHeight)
|
||||
height = glConfig.vidHeight;
|
||||
|
||||
Com_sprintf(fileName, sizeof(fileName), "levelshots/%s%s", tr.world->baseName, ext);
|
||||
|
||||
allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &spadlen);
|
||||
source = allsource + offset;
|
||||
|
||||
buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18);
|
||||
Com_Memset (buffer, 0, 18);
|
||||
buffer[2] = 2; // uncompressed type
|
||||
buffer[12] = 128;
|
||||
buffer[14] = 128;
|
||||
buffer[16] = 24; // pixel size
|
||||
linelen = width * 3;
|
||||
memcount = linelen * height;
|
||||
|
||||
resample = ri.Hunk_AllocateTempMemory(memcount);
|
||||
|
||||
// resample from source
|
||||
xScale = glConfig.vidWidth / 512.0f;
|
||||
yScale = glConfig.vidHeight / 384.0f;
|
||||
for ( y = 0 ; y < 128 ; y++ ) {
|
||||
for ( x = 0 ; x < 128 ; x++ ) {
|
||||
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 + padlen) * (int)((y*3 + yy) * yScale) +
|
||||
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 = buffer + 18 + 3 * ( y * 128 + x );
|
||||
dst[0] = b / 12;
|
||||
dst = resample + 3 * ( y * width + x );
|
||||
dst[0] = r / 12;
|
||||
dst[1] = g / 12;
|
||||
dst[2] = r / 12;
|
||||
dst[2] = b / 12;
|
||||
}
|
||||
}
|
||||
|
||||
// gamma correct
|
||||
if ( glConfig.deviceSupportsGamma ) {
|
||||
R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
|
||||
}
|
||||
if(glConfig.deviceSupportsGamma)
|
||||
R_GammaCorrect(resample, memcount);
|
||||
|
||||
ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
|
||||
if ( type == ST_TGA )
|
||||
RE_SaveTGA(fileName, width, height, resample, 0);
|
||||
else if ( type == ST_JPEG )
|
||||
RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, resample, 0);
|
||||
else if ( type == ST_PNG )
|
||||
RE_SavePNG(fileName, width, height, resample, 0);
|
||||
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
ri.Hunk_FreeTempMemory(resample);
|
||||
ri.Hunk_FreeTempMemory(allsource);
|
||||
|
||||
ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
|
||||
ri.Printf( PRINT_ALL, "Wrote %s\n", fileName );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -640,13 +617,13 @@ screenshot [filename]
|
|||
Doesn't print the pacifier message if there is a second arg
|
||||
==================
|
||||
*/
|
||||
void R_ScreenShot_f (void) {
|
||||
void R_ScreenShotTGA_f (void) {
|
||||
char checkname[MAX_OSPATH];
|
||||
static int lastNumber = -1;
|
||||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot();
|
||||
R_LevelShot( ST_TGA, ".tga" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -670,7 +647,7 @@ void R_ScreenShot_f (void) {
|
|||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilename( lastNumber, checkname );
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".tga" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
|
@ -686,7 +663,7 @@ void R_ScreenShot_f (void) {
|
|||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_TGA );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
|
@ -699,7 +676,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot();
|
||||
R_LevelShot( ST_JPEG, ".jpg" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -723,7 +700,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilenameJPEG( lastNumber, checkname );
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".jpg" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
|
@ -731,7 +708,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( lastNumber == 10000 ) {
|
||||
if ( lastNumber >= 9999 ) {
|
||||
ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
|
||||
return;
|
||||
}
|
||||
|
@ -739,13 +716,66 @@ void R_ScreenShotJPEG_f (void) {
|
|||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_JPEG );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
}
|
||||
}
|
||||
|
||||
void R_ScreenShotPNG_f (void) {
|
||||
char checkname[MAX_OSPATH];
|
||||
static int lastNumber = -1;
|
||||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot( ST_PNG, ".png" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
|
||||
silent = qtrue;
|
||||
} else {
|
||||
silent = qfalse;
|
||||
}
|
||||
|
||||
if ( ri.Cmd_Argc() == 2 && !silent ) {
|
||||
// explicit filename
|
||||
Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.png", ri.Cmd_Argv( 1 ) );
|
||||
} else {
|
||||
// scan for a free filename
|
||||
|
||||
// if we have saved a previous screenshot, don't scan
|
||||
// again, because recording demo avis can involve
|
||||
// thousands of shots
|
||||
if ( lastNumber == -1 ) {
|
||||
lastNumber = 0;
|
||||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".png" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
break; // file doesn't exist
|
||||
}
|
||||
}
|
||||
|
||||
if ( lastNumber >= 9999 ) {
|
||||
ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_PNG );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
|
@ -1159,8 +1189,9 @@ void R_Register( void )
|
|||
ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
|
||||
ri.Cmd_AddCommand( "modellist", R_Modellist_f );
|
||||
ri.Cmd_AddCommand( "modelist", R_ModeList_f );
|
||||
ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
|
||||
ri.Cmd_AddCommand( "screenshot", R_ScreenShotTGA_f );
|
||||
ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
|
||||
ri.Cmd_AddCommand( "screenshotPNG", R_ScreenShotPNG_f );
|
||||
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
||||
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
||||
}
|
||||
|
@ -1277,6 +1308,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
|
|||
ri.Cmd_RemoveCommand( "modelist" );
|
||||
ri.Cmd_RemoveCommand( "screenshot" );
|
||||
ri.Cmd_RemoveCommand( "screenshotJPEG" );
|
||||
ri.Cmd_RemoveCommand( "screenshotPNG" );
|
||||
ri.Cmd_RemoveCommand( "gfxinfo" );
|
||||
ri.Cmd_RemoveCommand( "minimize" );
|
||||
|
||||
|
|
|
@ -1517,6 +1517,12 @@ typedef struct {
|
|||
int numDrawSurfs;
|
||||
} drawSurfsCommand_t;
|
||||
|
||||
typedef enum {
|
||||
ST_TGA,
|
||||
ST_JPEG,
|
||||
ST_PNG
|
||||
} screenshotType_e;
|
||||
|
||||
typedef struct {
|
||||
int commandId;
|
||||
int x;
|
||||
|
@ -1524,7 +1530,7 @@ typedef struct {
|
|||
int width;
|
||||
int height;
|
||||
char *fileName;
|
||||
qboolean jpeg;
|
||||
screenshotType_e type;
|
||||
} screenshotCommand_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -1597,10 +1603,12 @@ void RE_StretchPic ( float x, float y, float w, float h,
|
|||
float s1, float t1, float s2, float t2, qhandle_t hShader );
|
||||
void RE_BeginFrame( stereoFrame_t stereoFrame );
|
||||
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
|
||||
void RE_SavePNG(const char *filename, int width, int height, byte *data, int padding);
|
||||
void RE_SaveJPG(char * filename, int quality, int image_width, int image_height,
|
||||
unsigned char *image_buffer, int padding);
|
||||
size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
|
||||
int image_width, int image_height, byte *image_buffer, int padding);
|
||||
void RE_SaveTGA(char * filename, int image_width, int image_height, byte *image_buffer, int padding);
|
||||
void RE_TakeVideoFrame( int width, int height,
|
||||
byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
|
||||
|
||||
|
|
|
@ -504,63 +504,24 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa
|
|||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshot
|
||||
RB_TakeScreenshotTGA
|
||||
==================
|
||||
*/
|
||||
void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
|
||||
void RB_TakeScreenshotTGA(int x, int y, int width, int height, char *fileName)
|
||||
{
|
||||
byte *allbuf, *buffer;
|
||||
byte *srcptr, *destptr;
|
||||
byte *endline, *endmem;
|
||||
byte temp;
|
||||
|
||||
int linelen, padlen;
|
||||
size_t offset = 18, memcount;
|
||||
|
||||
allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
|
||||
buffer = allbuf + offset - 18;
|
||||
|
||||
Com_Memset (buffer, 0, 18);
|
||||
buffer[2] = 2; // uncompressed type
|
||||
buffer[12] = width & 255;
|
||||
buffer[13] = width >> 8;
|
||||
buffer[14] = height & 255;
|
||||
buffer[15] = height >> 8;
|
||||
buffer[16] = 24; // pixel size
|
||||
byte *buffer;
|
||||
size_t offset = 0, memcount;
|
||||
int padlen;
|
||||
|
||||
// swap rgb to bgr and remove padding from line endings
|
||||
linelen = width * 3;
|
||||
|
||||
srcptr = destptr = allbuf + offset;
|
||||
endmem = srcptr + (linelen + padlen) * height;
|
||||
|
||||
while(srcptr < endmem)
|
||||
{
|
||||
endline = srcptr + linelen;
|
||||
|
||||
while(srcptr < endline)
|
||||
{
|
||||
temp = srcptr[0];
|
||||
*destptr++ = srcptr[2];
|
||||
*destptr++ = srcptr[1];
|
||||
*destptr++ = temp;
|
||||
|
||||
srcptr += 3;
|
||||
}
|
||||
|
||||
// Skip the pad
|
||||
srcptr += padlen;
|
||||
}
|
||||
|
||||
memcount = linelen * height;
|
||||
buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen);
|
||||
memcount = (width * 3 + padlen) * height;
|
||||
|
||||
// gamma correct
|
||||
if(glConfig.deviceSupportsGamma)
|
||||
R_GammaCorrect(allbuf + offset, memcount);
|
||||
R_GammaCorrect(buffer + offset, memcount);
|
||||
|
||||
ri.FS_WriteFile(fileName, buffer, memcount + 18);
|
||||
|
||||
ri.Hunk_FreeTempMemory(allbuf);
|
||||
RE_SaveTGA(fileName, width, height, buffer + offset, padlen);
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -586,6 +547,28 @@ void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
|
|||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshotPNG
|
||||
==================
|
||||
*/
|
||||
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, padlen);
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RB_TakeScreenshotCmd
|
||||
|
@ -600,10 +583,12 @@ const void *RB_TakeScreenshotCmd( const void *data ) {
|
|||
if(tess.numIndexes)
|
||||
RB_EndSurface();
|
||||
|
||||
if (cmd->jpeg)
|
||||
RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
||||
else
|
||||
RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
||||
if (cmd->type == ST_TGA)
|
||||
RB_TakeScreenshotTGA( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
else if (cmd->type == ST_JPEG)
|
||||
RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
else if (cmd->type == ST_PNG)
|
||||
RB_TakeScreenshotPNG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName );
|
||||
|
||||
return (const void *)(cmd + 1);
|
||||
}
|
||||
|
@ -613,7 +598,7 @@ const void *RB_TakeScreenshotCmd( const void *data ) {
|
|||
R_TakeScreenshot
|
||||
==================
|
||||
*/
|
||||
void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
|
||||
void R_TakeScreenshot( int x, int y, int width, int height, char *name, screenshotType_e type ) {
|
||||
static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
|
||||
screenshotCommand_t *cmd;
|
||||
|
||||
|
@ -629,7 +614,7 @@ void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean
|
|||
cmd->height = height;
|
||||
Q_strncpyz( fileName, name, sizeof(fileName) );
|
||||
cmd->fileName = fileName;
|
||||
cmd->jpeg = jpeg;
|
||||
cmd->type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -637,11 +622,11 @@ void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean
|
|||
R_ScreenshotFilename
|
||||
==================
|
||||
*/
|
||||
void R_ScreenshotFilename( int lastNumber, char *fileName ) {
|
||||
void R_ScreenshotFilename( int lastNumber, char *fileName, char *ext ) {
|
||||
int a,b,c,d;
|
||||
|
||||
if ( lastNumber < 0 || lastNumber > 9999 ) {
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999%s", ext );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -653,33 +638,8 @@ void R_ScreenshotFilename( int lastNumber, char *fileName ) {
|
|||
lastNumber -= c*10;
|
||||
d = lastNumber;
|
||||
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
|
||||
, a, b, c, d );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ScreenshotFilename
|
||||
==================
|
||||
*/
|
||||
void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
|
||||
int a,b,c,d;
|
||||
|
||||
if ( lastNumber < 0 || lastNumber > 9999 ) {
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
|
||||
return;
|
||||
}
|
||||
|
||||
a = lastNumber / 1000;
|
||||
lastNumber -= a*1000;
|
||||
b = lastNumber / 100;
|
||||
lastNumber -= b*100;
|
||||
c = lastNumber / 10;
|
||||
lastNumber -= c*10;
|
||||
d = lastNumber;
|
||||
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
|
||||
, a, b, c, d );
|
||||
Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i%s"
|
||||
, a, b, c, d, ext );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -690,63 +650,80 @@ levelshots are specialized 128*128 thumbnails for
|
|||
the menu system, sampled down from full screen distorted images
|
||||
====================
|
||||
*/
|
||||
void R_LevelShot( void ) {
|
||||
char checkname[MAX_OSPATH];
|
||||
byte *buffer;
|
||||
void R_LevelShot( screenshotType_e type, const char *ext ) {
|
||||
char fileName[MAX_OSPATH];
|
||||
byte *source, *allsource;
|
||||
byte *resample;
|
||||
size_t offset = 0, memcount;
|
||||
int spadlen;
|
||||
int linelen;
|
||||
byte *src, *dst;
|
||||
size_t offset = 0;
|
||||
int padlen;
|
||||
int x, y;
|
||||
int r, g, b;
|
||||
float xScale, yScale;
|
||||
int xx, yy;
|
||||
int width, height;
|
||||
int arg;
|
||||
|
||||
Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName);
|
||||
// Allow custom resample width/height
|
||||
arg = atoi(ri.Cmd_Argv(2));
|
||||
if (arg > 0)
|
||||
width = height = arg;
|
||||
else
|
||||
width = height = 128;
|
||||
|
||||
allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen);
|
||||
if (width > glConfig.vidWidth)
|
||||
width = glConfig.vidWidth;
|
||||
if (height > glConfig.vidHeight)
|
||||
height = glConfig.vidHeight;
|
||||
|
||||
Com_sprintf(fileName, sizeof(fileName), "levelshots/%s%s", tr.world->baseName, ext);
|
||||
|
||||
allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &spadlen);
|
||||
source = allsource + offset;
|
||||
|
||||
buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18);
|
||||
Com_Memset (buffer, 0, 18);
|
||||
buffer[2] = 2; // uncompressed type
|
||||
buffer[12] = 128;
|
||||
buffer[14] = 128;
|
||||
buffer[16] = 24; // pixel size
|
||||
linelen = width * 3;
|
||||
memcount = linelen * height;
|
||||
|
||||
resample = ri.Hunk_AllocateTempMemory(memcount);
|
||||
|
||||
// resample from source
|
||||
xScale = glConfig.vidWidth / 512.0f;
|
||||
yScale = glConfig.vidHeight / 384.0f;
|
||||
for ( y = 0 ; y < 128 ; y++ ) {
|
||||
for ( x = 0 ; x < 128 ; x++ ) {
|
||||
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 + padlen) * (int)((y*3 + yy) * yScale) +
|
||||
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 = buffer + 18 + 3 * ( y * 128 + x );
|
||||
dst[0] = b / 12;
|
||||
dst = resample + 3 * ( y * width + x );
|
||||
dst[0] = r / 12;
|
||||
dst[1] = g / 12;
|
||||
dst[2] = r / 12;
|
||||
dst[2] = b / 12;
|
||||
}
|
||||
}
|
||||
|
||||
// gamma correct
|
||||
if ( glConfig.deviceSupportsGamma ) {
|
||||
R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
|
||||
}
|
||||
if(glConfig.deviceSupportsGamma)
|
||||
R_GammaCorrect(resample, memcount);
|
||||
|
||||
ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
|
||||
if ( type == ST_TGA )
|
||||
RE_SaveTGA(fileName, width, height, resample, 0);
|
||||
else if ( type == ST_JPEG )
|
||||
RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, resample, 0);
|
||||
else if ( type == ST_PNG )
|
||||
RE_SavePNG(fileName, width, height, resample, 0);
|
||||
|
||||
ri.Hunk_FreeTempMemory(buffer);
|
||||
ri.Hunk_FreeTempMemory(resample);
|
||||
ri.Hunk_FreeTempMemory(allsource);
|
||||
|
||||
ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
|
||||
ri.Printf( PRINT_ALL, "Wrote %s\n", fileName );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -761,13 +738,13 @@ screenshot [filename]
|
|||
Doesn't print the pacifier message if there is a second arg
|
||||
==================
|
||||
*/
|
||||
void R_ScreenShot_f (void) {
|
||||
void R_ScreenShotTGA_f (void) {
|
||||
char checkname[MAX_OSPATH];
|
||||
static int lastNumber = -1;
|
||||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot();
|
||||
R_LevelShot( ST_TGA, ".tga" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -791,7 +768,7 @@ void R_ScreenShot_f (void) {
|
|||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilename( lastNumber, checkname );
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".tga" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
|
@ -807,7 +784,7 @@ void R_ScreenShot_f (void) {
|
|||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_TGA );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
|
@ -820,7 +797,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot();
|
||||
R_LevelShot( ST_JPEG, ".jpg" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -844,7 +821,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilenameJPEG( lastNumber, checkname );
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".jpg" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
|
@ -852,7 +829,7 @@ void R_ScreenShotJPEG_f (void) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( lastNumber == 10000 ) {
|
||||
if ( lastNumber >= 9999 ) {
|
||||
ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
|
||||
return;
|
||||
}
|
||||
|
@ -860,13 +837,66 @@ void R_ScreenShotJPEG_f (void) {
|
|||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_JPEG );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
}
|
||||
}
|
||||
|
||||
void R_ScreenShotPNG_f (void) {
|
||||
char checkname[MAX_OSPATH];
|
||||
static int lastNumber = -1;
|
||||
qboolean silent;
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
|
||||
R_LevelShot( ST_PNG, ".png" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
|
||||
silent = qtrue;
|
||||
} else {
|
||||
silent = qfalse;
|
||||
}
|
||||
|
||||
if ( ri.Cmd_Argc() == 2 && !silent ) {
|
||||
// explicit filename
|
||||
Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.png", ri.Cmd_Argv( 1 ) );
|
||||
} else {
|
||||
// scan for a free filename
|
||||
|
||||
// if we have saved a previous screenshot, don't scan
|
||||
// again, because recording demo avis can involve
|
||||
// thousands of shots
|
||||
if ( lastNumber == -1 ) {
|
||||
lastNumber = 0;
|
||||
}
|
||||
// scan for a free number
|
||||
for ( ; lastNumber <= 9999 ; lastNumber++ ) {
|
||||
R_ScreenshotFilename( lastNumber, checkname, ".png" );
|
||||
|
||||
if (!ri.FS_FileExists( checkname ))
|
||||
{
|
||||
break; // file doesn't exist
|
||||
}
|
||||
}
|
||||
|
||||
if ( lastNumber >= 9999 ) {
|
||||
ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lastNumber++;
|
||||
}
|
||||
|
||||
R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, ST_PNG );
|
||||
|
||||
if ( !silent ) {
|
||||
ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
|
@ -1446,8 +1476,9 @@ void R_Register( void )
|
|||
ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
|
||||
ri.Cmd_AddCommand( "modellist", R_Modellist_f );
|
||||
ri.Cmd_AddCommand( "modelist", R_ModeList_f );
|
||||
ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
|
||||
ri.Cmd_AddCommand( "screenshot", R_ScreenShotTGA_f );
|
||||
ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
|
||||
ri.Cmd_AddCommand( "screenshotPNG", R_ScreenShotPNG_f );
|
||||
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
||||
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
||||
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
|
||||
|
@ -1593,6 +1624,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
|
|||
ri.Cmd_RemoveCommand( "modelist" );
|
||||
ri.Cmd_RemoveCommand( "screenshot" );
|
||||
ri.Cmd_RemoveCommand( "screenshotJPEG" );
|
||||
ri.Cmd_RemoveCommand( "screenshotPNG" );
|
||||
ri.Cmd_RemoveCommand( "gfxinfo" );
|
||||
ri.Cmd_RemoveCommand( "minimize" );
|
||||
ri.Cmd_RemoveCommand( "gfxmeminfo" );
|
||||
|
|
|
@ -2409,6 +2409,12 @@ typedef struct {
|
|||
int numDrawSurfs;
|
||||
} drawSurfsCommand_t;
|
||||
|
||||
typedef enum {
|
||||
ST_TGA,
|
||||
ST_JPEG,
|
||||
ST_PNG
|
||||
} screenshotType_e;
|
||||
|
||||
typedef struct {
|
||||
int commandId;
|
||||
int x;
|
||||
|
@ -2416,7 +2422,7 @@ typedef struct {
|
|||
int width;
|
||||
int height;
|
||||
char *fileName;
|
||||
qboolean jpeg;
|
||||
screenshotType_e type;
|
||||
} screenshotCommand_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -2511,10 +2517,12 @@ void RE_StretchPic ( float x, float y, float w, float h,
|
|||
float s1, float t1, float s2, float t2, qhandle_t hShader );
|
||||
void RE_BeginFrame( stereoFrame_t stereoFrame );
|
||||
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
|
||||
void RE_SavePNG(const char *filename, int width, int height, byte *data, int padding);
|
||||
void RE_SaveJPG(char * filename, int quality, int image_width, int image_height,
|
||||
unsigned char *image_buffer, int padding);
|
||||
size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
|
||||
int image_width, int image_height, byte *image_buffer, int padding);
|
||||
void RE_SaveTGA(char * filename, int image_width, int image_height, byte *image_buffer, int padding);
|
||||
void RE_TakeVideoFrame( int width, int height,
|
||||
byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
|
||||
|
||||
|
|
79
code/zlib/compress.c
Normal file
79
code/zlib/compress.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||
}
|
1736
code/zlib/deflate.c
Normal file
1736
code/zlib/deflate.c
Normal file
File diff suppressed because it is too large
Load diff
331
code/zlib/deflate.h
Normal file
331
code/zlib/deflate.h
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2004 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef DEFLATE_H
|
||||
#define DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GZIP
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
#define COMMENT_STATE 91
|
||||
#define HCRC_STATE 103
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
uInt pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
/* in trees.c */
|
||||
void _tr_init OF((deflate_state *s));
|
||||
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
void _tr_align OF((deflate_state *s));
|
||||
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
|
||||
#define d_code(dist) \
|
||||
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
* used.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||
extern uch _length_code[];
|
||||
extern uch _dist_code[];
|
||||
#else
|
||||
extern const uch _length_code[];
|
||||
extern const uch _dist_code[];
|
||||
#endif
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (length); \
|
||||
ush dist = (distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
flush = _tr_tally(s, distance, length)
|
||||
#endif
|
||||
|
||||
#endif /* DEFLATE_H */
|
1219
code/zlib/trees.c
Normal file
1219
code/zlib/trees.c
Normal file
File diff suppressed because it is too large
Load diff
128
code/zlib/trees.h
Normal file
128
code/zlib/trees.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* header created automatically with -DGEN_TREES_H */
|
||||
|
||||
local const ct_data static_ltree[L_CODES+2] = {
|
||||
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
||||
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
||||
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
||||
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
||||
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
||||
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
||||
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
||||
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
||||
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
||||
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
||||
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
||||
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
||||
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
||||
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
||||
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
||||
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
||||
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
||||
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
||||
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
||||
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
||||
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
||||
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
||||
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
||||
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
||||
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
||||
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
||||
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
||||
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
||||
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
||||
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
||||
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
||||
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
||||
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
||||
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
||||
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
||||
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
||||
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
||||
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
||||
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
||||
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
||||
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
||||
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
||||
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
||||
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
||||
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
||||
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
||||
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
||||
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
||||
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
||||
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
||||
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
||||
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
||||
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
||||
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
||||
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
||||
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
||||
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
||||
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
||||
};
|
||||
|
||||
local const ct_data static_dtree[D_CODES] = {
|
||||
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
||||
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
||||
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
||||
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
||||
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
||||
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
||||
};
|
||||
|
||||
const uch _dist_code[DIST_CODE_LEN] = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
local const int base_length[LENGTH_CODES] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
local const int base_dist[D_CODES] = {
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue