mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-01-18 21:21:36 +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)
|
August 11, 2006 (Changes by Graf Zahl)
|
||||||
- Fixed: P_CheckOnMobjZ returned the first thing an actor could stand on,
|
- Fixed: P_CheckOnMobjZ returned the first thing an actor could stand on,
|
||||||
not the highest possible.
|
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 inline void StuffPalette (const PalEntry *from, BYTE *to);
|
||||||
static bool StuffBitmap (const DCanvas *canvas, FILE *file);
|
static bool StuffBitmap (const DCanvas *canvas, FILE *file);
|
||||||
static bool WriteIDAT (FILE *file, const BYTE *data, int len);
|
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);
|
static void UnpackPixels (int width, int bytesPerRow, int bitdepth, BYTE *row);
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
@ -532,14 +532,27 @@ bool M_ReadIDAT (FileReader *file, BYTE *buffer, int width, int height, int pitc
|
||||||
int y;
|
int y;
|
||||||
bool lastIDAT;
|
bool lastIDAT;
|
||||||
int bytesPerRowIn;
|
int bytesPerRowIn;
|
||||||
|
int bytesPerPixel;
|
||||||
|
|
||||||
inputLine = (Byte *)alloca (1+width*2);
|
switch (colortype)
|
||||||
prev = inputLine + 1 + width;
|
{
|
||||||
memset (prev, 0, width);
|
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)
|
switch (bitdepth)
|
||||||
{
|
{
|
||||||
case 8: bytesPerRowIn = width; break;
|
case 8: bytesPerRowIn = width * bytesPerPixel; break;
|
||||||
case 4: bytesPerRowIn = (width+1)/2; break;
|
case 4: bytesPerRowIn = (width+1)/2; break;
|
||||||
case 2: bytesPerRowIn = (width+3)/4; break;
|
case 2: bytesPerRowIn = (width+3)/4; break;
|
||||||
case 1: bytesPerRowIn = (width+7)/8; break;
|
case 1: bytesPerRowIn = (width+7)/8; break;
|
||||||
|
@ -581,7 +594,7 @@ bool M_ReadIDAT (FileReader *file, BYTE *buffer, int width, int height, int pitc
|
||||||
|
|
||||||
if (stream.avail_out == 0)
|
if (stream.avail_out == 0)
|
||||||
{
|
{
|
||||||
UnfilterRow (bytesPerRowIn, curr, inputLine, prev);
|
UnfilterRow (bytesPerRowIn, curr, inputLine, prev, bytesPerPixel);
|
||||||
prev = curr;
|
prev = curr;
|
||||||
curr += pitch;
|
curr += pitch;
|
||||||
y++;
|
y++;
|
||||||
|
@ -800,51 +813,77 @@ static bool WriteIDAT (FILE *file, const BYTE *data, int len)
|
||||||
// UnfilterRow
|
// UnfilterRow
|
||||||
//
|
//
|
||||||
// Unfilters the given row. Unknown filter types are silently ignored.
|
// 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;
|
int x;
|
||||||
|
|
||||||
switch (*row++)
|
switch (*row++)
|
||||||
{
|
{
|
||||||
case 1: // Sub
|
case 1: // Sub
|
||||||
dest[0] = row[0];
|
x = bpp;
|
||||||
for (x = 1; x < width; ++x)
|
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;
|
break;
|
||||||
|
|
||||||
case 2: // Up
|
case 2: // Up
|
||||||
for (x = 0; x < width; ++x)
|
x = width;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
dest[x] = row[x] + prev[x];
|
*dest++ = *row++ + *prev++;
|
||||||
}
|
}
|
||||||
|
while (--x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Average
|
case 3: // Average
|
||||||
dest[0] = row[0] + prev[0]/2;
|
x = bpp;
|
||||||
for (x = 1; x < width; ++x)
|
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;
|
break;
|
||||||
|
|
||||||
case 4: // Paeth
|
case 4: // Paeth
|
||||||
dest[0] = row[0] + prev[0];
|
x = bpp;
|
||||||
for (x = 1; x < width; ++x)
|
do
|
||||||
|
{
|
||||||
|
*dest++ = *row++ + *prev++;
|
||||||
|
}
|
||||||
|
while (--x);
|
||||||
|
for (x = width - bpp; x > 0; --x)
|
||||||
{
|
{
|
||||||
int a, b, c, pa, pb, pc;
|
int a, b, c, pa, pb, pc;
|
||||||
|
|
||||||
a = dest[x-1];
|
a = *(dest - bpp);
|
||||||
b = prev[x];
|
b = *(prev);
|
||||||
c = prev[x-1];
|
c = *(prev - bpp);
|
||||||
pa = abs (b - c);
|
pa = b - c;
|
||||||
pb = abs (a - c);
|
pb = a - c;
|
||||||
pc = abs (a + b - c - c);
|
pc = abs (pa + pb);
|
||||||
dest[x] = row[x] + (BYTE)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
|
pa = abs (pa);
|
||||||
|
pb = abs (pb);
|
||||||
|
*dest = *row + (BYTE)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
|
||||||
|
dest++;
|
||||||
|
row++;
|
||||||
|
prev++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
122
src/r_data.cpp
122
src/r_data.cpp
|
@ -279,7 +279,11 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (colortype != 0 && colortype != 3)
|
if (!((1 << colortype) & 0x5D))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!((1 << bitdepth) & 0x116))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1853,21 +1857,13 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
||||||
}
|
}
|
||||||
StartOfIDAT = lump.Tell() - 8;
|
StartOfIDAT = lump.Tell() - 8;
|
||||||
|
|
||||||
if (colortype == 3)
|
switch (colortype)
|
||||||
{
|
|
||||||
PaletteMap = new BYTE[PaletteSize];
|
|
||||||
GPalette.MakeRemap (palette, PaletteMap, trans, PaletteSize);
|
|
||||||
for (i = 0; i < PaletteSize; ++i)
|
|
||||||
{
|
|
||||||
if (trans[i] == 0)
|
|
||||||
{
|
{
|
||||||
|
case 4: // Grayscale + Alpha
|
||||||
bMasked = true;
|
bMasked = true;
|
||||||
PaletteMap[i] = 0;
|
// intentional fall-through
|
||||||
}
|
|
||||||
}
|
case 0: // Grayscale
|
||||||
}
|
|
||||||
else if (colortype == 0)
|
|
||||||
{
|
|
||||||
if (!bAlphaTexture)
|
if (!bAlphaTexture)
|
||||||
{
|
{
|
||||||
if (GrayMap[0] == GrayMap[255])
|
if (GrayMap[0] == GrayMap[255])
|
||||||
|
@ -1877,7 +1873,7 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
||||||
GrayMap[i] = ColorMatcher.Pick (i, i, i);
|
GrayMap[i] = ColorMatcher.Pick (i, i, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (havetRNS && trans[0] != 0)
|
if (colortype == 0 && havetRNS && trans[0] != 0)
|
||||||
{
|
{
|
||||||
bMasked = true;
|
bMasked = true;
|
||||||
PaletteSize = 256;
|
PaletteSize = 256;
|
||||||
|
@ -1890,6 +1886,24 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
||||||
PaletteMap = GrayMap;
|
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,6 +1978,9 @@ void FPNGTexture::MakeTexture ()
|
||||||
DWORD len, id;
|
DWORD len, id;
|
||||||
lump.Seek (StartOfIDAT, SEEK_SET);
|
lump.Seek (StartOfIDAT, SEEK_SET);
|
||||||
lump >> len >> id;
|
lump >> len >> id;
|
||||||
|
|
||||||
|
if (ColorType == 0 || ColorType == 3) /* Grayscale and paletted */
|
||||||
|
{
|
||||||
M_ReadIDAT (&lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len));
|
M_ReadIDAT (&lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len));
|
||||||
|
|
||||||
if (Width == Height)
|
if (Width == Height)
|
||||||
|
@ -1993,6 +2010,81 @@ void FPNGTexture::MakeTexture ()
|
||||||
delete[] oldpix;
|
delete[] oldpix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else /* RGB and/or Alpha present */
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
delete[] tempix;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Spans == NULL)
|
if (Spans == NULL)
|
||||||
{
|
{
|
||||||
Spans = CreateSpans (Pixels);
|
Spans = CreateSpans (Pixels);
|
||||||
|
|
Loading…
Reference in a new issue