mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-01-18 13:11:37 +00:00
- Added support for truecolor PNG textures. They still get resampled to the
global palette, but at least they are visible now. - Optimized UnfilterRow() in m_png.cpp a little. SVN r291 (trunk)
This commit is contained in:
parent
8ecfe6a8ac
commit
89396964f5
3 changed files with 195 additions and 59 deletions
|
@ -1,3 +1,8 @@
|
|||
August 12, 2006
|
||||
- Added support for truecolor PNG textures. They still get resampled to the
|
||||
global palette, but at least they are visible now.
|
||||
- Optimized UnfilterRow() in m_png.cpp a little.
|
||||
|
||||
August 11, 2006 (Changes by Graf Zahl)
|
||||
- Fixed: P_CheckOnMobjZ returned the first thing an actor could stand on,
|
||||
not the highest possible.
|
||||
|
|
|
@ -99,7 +99,7 @@ static inline void MakeChunk (void *where, DWORD type, size_t len);
|
|||
static inline void StuffPalette (const PalEntry *from, BYTE *to);
|
||||
static bool StuffBitmap (const DCanvas *canvas, FILE *file);
|
||||
static bool WriteIDAT (FILE *file, const BYTE *data, int len);
|
||||
static void UnfilterRow (int width, BYTE *dest, BYTE *stream, BYTE *prev);
|
||||
static void UnfilterRow (int width, BYTE *dest, BYTE *stream, BYTE *prev, int bpp);
|
||||
static void UnpackPixels (int width, int bytesPerRow, int bitdepth, BYTE *row);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
@ -532,17 +532,30 @@ bool M_ReadIDAT (FileReader *file, BYTE *buffer, int width, int height, int pitc
|
|||
int y;
|
||||
bool lastIDAT;
|
||||
int bytesPerRowIn;
|
||||
int bytesPerPixel;
|
||||
|
||||
inputLine = (Byte *)alloca (1+width*2);
|
||||
prev = inputLine + 1 + width;
|
||||
memset (prev, 0, width);
|
||||
switch (colortype)
|
||||
{
|
||||
case 2: bytesPerPixel = 3; break; // RGB
|
||||
case 4: bytesPerPixel = 2; break; // LA
|
||||
case 6: bytesPerPixel = 4; break; // RGBA
|
||||
default: bytesPerPixel = 1; break;
|
||||
}
|
||||
inputLine = (Byte *)alloca (1 + width*bytesPerPixel*2);
|
||||
prev = inputLine + 1 + width*bytesPerPixel;
|
||||
memset (prev, 0, width*bytesPerPixel);
|
||||
|
||||
if (bytesPerPixel == 1 && bitdepth != 8)
|
||||
{ // This is an invalid combination for PNG files
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (bitdepth)
|
||||
{
|
||||
case 8: bytesPerRowIn = width; break;
|
||||
case 4: bytesPerRowIn = (width+1)/2; break;
|
||||
case 2: bytesPerRowIn = (width+3)/4; break;
|
||||
case 1: bytesPerRowIn = (width+7)/8; break;
|
||||
case 8: bytesPerRowIn = width * bytesPerPixel; break;
|
||||
case 4: bytesPerRowIn = (width+1)/2; break;
|
||||
case 2: bytesPerRowIn = (width+3)/4; break;
|
||||
case 1: bytesPerRowIn = (width+7)/8; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
|
@ -581,7 +594,7 @@ bool M_ReadIDAT (FileReader *file, BYTE *buffer, int width, int height, int pitc
|
|||
|
||||
if (stream.avail_out == 0)
|
||||
{
|
||||
UnfilterRow (bytesPerRowIn, curr, inputLine, prev);
|
||||
UnfilterRow (bytesPerRowIn, curr, inputLine, prev, bytesPerPixel);
|
||||
prev = curr;
|
||||
curr += pitch;
|
||||
y++;
|
||||
|
@ -800,51 +813,77 @@ static bool WriteIDAT (FILE *file, const BYTE *data, int len)
|
|||
// UnfilterRow
|
||||
//
|
||||
// Unfilters the given row. Unknown filter types are silently ignored.
|
||||
// bpp is bytes per pixel, not bits per pixel.
|
||||
// width is in bytes, not pixels.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void UnfilterRow (int width, BYTE *dest, BYTE *row, BYTE *prev)
|
||||
void UnfilterRow (int width, BYTE *dest, BYTE *row, BYTE *prev, int bpp)
|
||||
{
|
||||
int x;
|
||||
|
||||
switch (*row++)
|
||||
{
|
||||
case 1: // Sub
|
||||
dest[0] = row[0];
|
||||
for (x = 1; x < width; ++x)
|
||||
x = bpp;
|
||||
do
|
||||
{
|
||||
dest[x] = row[x] + dest[x-1];
|
||||
*dest++ = *row++;
|
||||
}
|
||||
while (--x);
|
||||
for (x = width - bpp; x > 0; --x)
|
||||
{
|
||||
*dest = *row++ + *(dest - bpp);
|
||||
dest++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Up
|
||||
for (x = 0; x < width; ++x)
|
||||
x = width;
|
||||
do
|
||||
{
|
||||
dest[x] = row[x] + prev[x];
|
||||
*dest++ = *row++ + *prev++;
|
||||
}
|
||||
while (--x);
|
||||
break;
|
||||
|
||||
case 3: // Average
|
||||
dest[0] = row[0] + prev[0]/2;
|
||||
for (x = 1; x < width; ++x)
|
||||
x = bpp;
|
||||
do
|
||||
{
|
||||
dest[x] = row[x] + (BYTE)(((unsigned)dest[x-1] + (unsigned)prev[x])/2);
|
||||
*dest++ = *row++ + (*prev++)/2;
|
||||
}
|
||||
while (--x);
|
||||
for (x = width - bpp; x > 0; --x)
|
||||
{
|
||||
*dest = *row++ + (BYTE)((unsigned(*(dest - bpp)) + unsigned(*prev++)) >> 1);
|
||||
dest++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Paeth
|
||||
dest[0] = row[0] + prev[0];
|
||||
for (x = 1; x < width; ++x)
|
||||
x = bpp;
|
||||
do
|
||||
{
|
||||
*dest++ = *row++ + *prev++;
|
||||
}
|
||||
while (--x);
|
||||
for (x = width - bpp; x > 0; --x)
|
||||
{
|
||||
int a, b, c, pa, pb, pc;
|
||||
|
||||
a = dest[x-1];
|
||||
b = prev[x];
|
||||
c = prev[x-1];
|
||||
pa = abs (b - c);
|
||||
pb = abs (a - c);
|
||||
pc = abs (a + b - c - c);
|
||||
dest[x] = row[x] + (BYTE)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
|
||||
a = *(dest - bpp);
|
||||
b = *(prev);
|
||||
c = *(prev - bpp);
|
||||
pa = b - c;
|
||||
pb = a - c;
|
||||
pc = abs (pa + pb);
|
||||
pa = abs (pa);
|
||||
pb = abs (pb);
|
||||
*dest = *row + (BYTE)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
|
||||
dest++;
|
||||
row++;
|
||||
prev++;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
156
src/r_data.cpp
156
src/r_data.cpp
|
@ -279,7 +279,11 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype)
|
|||
{
|
||||
return -1;
|
||||
}
|
||||
if (colortype != 0 && colortype != 3)
|
||||
if (!((1 << colortype) & 0x5D))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!((1 << bitdepth) & 0x116))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -1853,21 +1857,13 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
|||
}
|
||||
StartOfIDAT = lump.Tell() - 8;
|
||||
|
||||
if (colortype == 3)
|
||||
{
|
||||
PaletteMap = new BYTE[PaletteSize];
|
||||
GPalette.MakeRemap (palette, PaletteMap, trans, PaletteSize);
|
||||
for (i = 0; i < PaletteSize; ++i)
|
||||
{
|
||||
if (trans[i] == 0)
|
||||
{
|
||||
bMasked = true;
|
||||
PaletteMap[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (colortype == 0)
|
||||
switch (colortype)
|
||||
{
|
||||
case 4: // Grayscale + Alpha
|
||||
bMasked = true;
|
||||
// intentional fall-through
|
||||
|
||||
case 0: // Grayscale
|
||||
if (!bAlphaTexture)
|
||||
{
|
||||
if (GrayMap[0] == GrayMap[255])
|
||||
|
@ -1877,7 +1873,7 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
|||
GrayMap[i] = ColorMatcher.Pick (i, i, i);
|
||||
}
|
||||
}
|
||||
if (havetRNS && trans[0] != 0)
|
||||
if (colortype == 0 && havetRNS && trans[0] != 0)
|
||||
{
|
||||
bMasked = true;
|
||||
PaletteSize = 256;
|
||||
|
@ -1890,6 +1886,24 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
|||
PaletteMap = GrayMap;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Paletted
|
||||
PaletteMap = new BYTE[PaletteSize];
|
||||
GPalette.MakeRemap (palette, PaletteMap, trans, PaletteSize);
|
||||
for (i = 0; i < PaletteSize; ++i)
|
||||
{
|
||||
if (trans[i] == 0)
|
||||
{
|
||||
bMasked = true;
|
||||
PaletteMap[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // RGB + Alpha
|
||||
bMasked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1964,33 +1978,111 @@ void FPNGTexture::MakeTexture ()
|
|||
DWORD len, id;
|
||||
lump.Seek (StartOfIDAT, SEEK_SET);
|
||||
lump >> len >> id;
|
||||
M_ReadIDAT (&lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len));
|
||||
|
||||
if (Width == Height)
|
||||
if (ColorType == 0 || ColorType == 3) /* Grayscale and paletted */
|
||||
{
|
||||
if (PaletteMap != NULL)
|
||||
M_ReadIDAT (&lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len));
|
||||
|
||||
if (Width == Height)
|
||||
{
|
||||
FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap);
|
||||
if (PaletteMap != NULL)
|
||||
{
|
||||
FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlipSquareBlock (Pixels, Width, Height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FlipSquareBlock (Pixels, Width, Height);
|
||||
BYTE *newpix = new BYTE[Width*Height];
|
||||
if (PaletteMap != NULL)
|
||||
{
|
||||
FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, PaletteMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlipNonSquareBlock (newpix, Pixels, Width, Height, Width);
|
||||
}
|
||||
BYTE *oldpix = Pixels;
|
||||
Pixels = newpix;
|
||||
delete[] oldpix;
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* RGB and/or Alpha present */
|
||||
{
|
||||
BYTE *newpix = new BYTE[Width*Height];
|
||||
if (PaletteMap != NULL)
|
||||
int bytesPerPixel = ColorType == 2 ? 3 : ColorType == 4 ? 2 : 4;
|
||||
BYTE *tempix = new BYTE[Width * Height * bytesPerPixel];
|
||||
BYTE *in, *out;
|
||||
int x, y, pitch, backstep;
|
||||
|
||||
M_ReadIDAT (&lump, tempix, Width, Height, Width*bytesPerPixel, BitDepth, ColorType, Interlace, BigLong((unsigned int)len));
|
||||
in = tempix;
|
||||
out = Pixels;
|
||||
|
||||
// Convert from source format to paletted, column-major.
|
||||
// Formats with alpha maps are reduced to only 1 bit of alpha.
|
||||
switch (ColorType)
|
||||
{
|
||||
FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, PaletteMap);
|
||||
case 2: // RGB
|
||||
pitch = Width * 3;
|
||||
backstep = Height * pitch - 3;
|
||||
for (x = Width; x > 0; --x)
|
||||
{
|
||||
for (y = Height; y > 0; --y)
|
||||
{
|
||||
*out++ = RGB32k[in[0]>>3][in[1]>>3][in[2]>>3];
|
||||
in += pitch;
|
||||
}
|
||||
in -= backstep;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Grayscale + Alpha
|
||||
pitch = Width * 2;
|
||||
backstep = Height * pitch - 2;
|
||||
if (PaletteMap != NULL)
|
||||
{
|
||||
for (x = Width; x > 0; --x)
|
||||
{
|
||||
for (y = Height; y > 0; --y)
|
||||
{
|
||||
*out++ = in[1] < 128 ? 0 : PaletteMap[in[0]];
|
||||
in += pitch;
|
||||
}
|
||||
in -= backstep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = Width; x > 0; --x)
|
||||
{
|
||||
for (y = Height; y > 0; --y)
|
||||
{
|
||||
*out++ = in[1] < 128 ? 0 : in[0];
|
||||
in += pitch;
|
||||
}
|
||||
in -= backstep;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // RGB + Alpha
|
||||
pitch = Width * 4;
|
||||
backstep = Height * pitch - 4;
|
||||
for (x = Width; x > 0; --x)
|
||||
{
|
||||
for (y = Height; y > 0; --y)
|
||||
{
|
||||
*out++ = in[3] < 128 ? 0 : RGB32k[in[0]>>3][in[1]>>3][in[2]>>3];
|
||||
in += pitch;
|
||||
}
|
||||
in -= backstep;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlipNonSquareBlock (newpix, Pixels, Width, Height, Width);
|
||||
}
|
||||
BYTE *oldpix = Pixels;
|
||||
Pixels = newpix;
|
||||
delete[] oldpix;
|
||||
delete[] tempix;
|
||||
}
|
||||
}
|
||||
if (Spans == NULL)
|
||||
|
|
Loading…
Reference in a new issue