diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b00085513..db564624c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,5 @@ +August 21, 2006 (Changes by Graf Zahl) +- Added support for PCX textures (1, 4, 8 and 24 bit variants.) August 20, 2006 (Changes by Graf Zahl) - Changed: Patch and IMGZ textures now initialize their dimensions upon creation. diff --git a/src/r_data.h b/src/r_data.h index d64a9f181..97a860803 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -288,6 +288,28 @@ protected: }; // A TGA texture + +#pragma pack(1) + +struct TGAHeader +{ + BYTE id_len; + BYTE has_cm; + BYTE img_type; + SWORD cm_first; + SWORD cm_length; + BYTE cm_size; + + SWORD x_origin; + SWORD y_origin; + SWORD width; + SWORD height; + BYTE bpp; + BYTE img_desc; +}; + +#pragma pack() + struct TGAHeader; class FTGATexture : public FTexture @@ -314,6 +336,63 @@ protected: friend class FTexture; }; +// A PCX texture + +#pragma pack(1) + +struct PCXHeader +{ + BYTE manufacturer; + BYTE version; + BYTE encoding; + BYTE bitsPerPixel; + + WORD xmin, ymin; + WORD xmax, ymax; + WORD horzRes, vertRes; + + BYTE palette[48]; + BYTE reserved; + BYTE numColorPlanes; + + WORD bytesPerScanLine; + WORD paletteType; + WORD horzSize, vertSize; + + BYTE padding[54]; + +}; +#pragma pack() + +class FPCXTexture : public FTexture +{ +public: + ~FPCXTexture (); + + const BYTE *GetColumn (unsigned int column, const Span **spans_out); + const BYTE *GetPixels (); + void Unload (); + +protected: + int SourceLump; + BYTE *Pixels; + Span DummySpans[2]; + + static bool Check(FileReader & file); + static FTexture *Create(FileReader & file, int lumpnum); + FPCXTexture (int lumpnum, PCXHeader &); + void ReadPCX1bit (BYTE *dst, FileReader & lump, PCXHeader *hdr); + void ReadPCX4bits (BYTE *dst, FileReader & lump, PCXHeader *hdr); + void ReadPCX8bits (BYTE *dst, FileReader & lump, PCXHeader *hdr); + void ReadPCX24bits (BYTE *dst, FileReader & lump, PCXHeader *hdr, int planes); + + virtual void MakeTexture (); + + friend class FTexture; +}; + + + // A texture that returns a wiggly version of another texture. class FWarpTexture : public FTexture { diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp new file mode 100644 index 000000000..c1f81d2b4 --- /dev/null +++ b/src/textures/pcxtexture.cpp @@ -0,0 +1,402 @@ +/* +** pcxtexture.cpp +** Texture class for PCX images +** +**--------------------------------------------------------------------------- +** Copyright 2005 David HENRY +** Copyright 2006 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "doomtype.h" +#include "files.h" +#include "r_local.h" +#include "w_wad.h" +#include "templates.h" + + +bool FPCXTexture::Check(FileReader & file) +{ + PCXHeader hdr; + + file.Seek(0, SEEK_SET); + file.Read(&hdr, sizeof(hdr)); + +#ifdef WORDS_BIGENDIAN + hdr.xmin = LittleShort(hdr.xmin); + hdr.xmax = LittleShort(hdr.xmax); + hdr.bytesPerScanLine = LittleShort(hdr.bytesPerScanLine); +#endif + + if (hdr.manufacturer != 10 || hdr.encoding != 1) return false; + if (hdr.version != 0 && hdr.version != 2 && hdr.version != 3 && hdr.version != 4 && hdr.version != 5) return false; + if (hdr.bitsPerPixel != 1 && hdr.bitsPerPixel != 8) return false; + if (hdr.bitsPerPixel == 1 && hdr.numColorPlanes !=1 && hdr.numColorPlanes != 4) return false; + if (hdr.bitsPerPixel == 8 && hdr.bytesPerScanLine != ((hdr.xmax - hdr.xmin + 2)&~1)) return false; + + for (int i = 0; i < 54; i++) + { + if (hdr.padding[i] != 0) return false; + } + return true; +} + +FTexture * FPCXTexture::Create(FileReader & file, int lumpnum) +{ + PCXHeader hdr; + + file.Seek(0, SEEK_SET); + file.Read(&hdr, sizeof(hdr)); + + return new FPCXTexture(lumpnum, hdr); +} + +FPCXTexture::FPCXTexture(int lumpnum, PCXHeader & hdr) +: SourceLump(lumpnum), Pixels(0) +{ + Wads.GetLumpName (Name, lumpnum); + Name[8] = 0; + bMasked = false; + Width = LittleShort(hdr.xmax) - LittleShort(hdr.xmin) + 1; + Height = LittleShort(hdr.ymax) - LittleShort(hdr.ymin) + 1; + CalcBitSize(); + + DummySpans[0].TopOffset = 0; + DummySpans[0].Length = Height; + DummySpans[1].TopOffset = 0; + DummySpans[1].Length = 0; +} + +FPCXTexture::~FPCXTexture () +{ + Unload (); +} + + +void FPCXTexture::Unload () +{ + if (Pixels != NULL) + { + delete[] Pixels; + Pixels = NULL; + } +} + +const BYTE *FPCXTexture::GetColumn (unsigned int column, const Span **spans_out) +{ + if (Pixels == NULL) + { + MakeTexture (); + } + if ((unsigned)column >= (unsigned)Width) + { + if (WidthMask + 1 == Width) + { + column &= WidthMask; + } + else + { + column %= Width; + } + } + if (spans_out != NULL) + { + *spans_out = DummySpans; + } + return Pixels + column*Height; +} + +const BYTE *FPCXTexture::GetPixels () +{ + if (Pixels == NULL) + { + MakeTexture (); + } + return Pixels; +} + +void FPCXTexture::ReadPCX1bit (BYTE *dst, FileReader & lump, PCXHeader *hdr) +{ + int y, i, bytes; + int rle_count = 0; + BYTE rle_value = 0; + + BYTE * srcp = new BYTE[lump.GetLength() - sizeof(PCXHeader)]; + lump.Read(srcp, lump.GetLength() - sizeof(PCXHeader)); + BYTE * src = srcp; + + for (y = 0; y < Height; ++y) + { + BYTE * ptr = &dst[y * Width]; + + bytes = hdr->bytesPerScanLine; + + while (bytes--) + { + if (rle_count == 0) + { + if ( (rle_value = *src++) < 0xc0) + { + rle_count = 1; + } + else + { + rle_count = rle_value - 0xc0; + rle_value = *src++; + } + } + + rle_count--; + + for (i = 7; i >= 0; --i, ptr ++) + { + *ptr = ((rle_value & (1 << i)) > 0); + } + } + } + delete [] srcp; +} + + +void FPCXTexture::ReadPCX4bits (BYTE *dst, FileReader & lump, PCXHeader *hdr) +{ + int rle_count = 0, rle_value = 0; + int x, y, c; + int bytes; + BYTE * line = new BYTE[hdr->bytesPerScanLine]; + BYTE * colorIndex = new BYTE[Width]; + + BYTE * srcp = new BYTE[lump.GetLength() - sizeof(PCXHeader)]; + lump.Read(srcp, lump.GetLength() - sizeof(PCXHeader)); + BYTE * src = srcp; + + for (y = 0; y < Height; ++y) + { + BYTE * ptr = &dst[y * Width]; + memset (ptr, 0, Width * sizeof (BYTE)); + + for (c = 0; c < 4; ++c) + { + BYTE * pLine = line; + + bytes = hdr->bytesPerScanLine; + + while (bytes--) + { + if (rle_count == 0) + { + if ( (rle_value = *src++) < 0xc0) + { + rle_count = 1; + } + else + { + rle_count = rle_value - 0xc0; + rle_value = *src++; + } + } + + rle_count--; + *(pLine++) = rle_value; + } + + /* compute line's color indexes */ + for (x = 0; x < Width; ++x) + { + if (line[x / 8] & (128 >> (x % 8))) + ptr[x] += (1 << c); + } + } + } + + /* release memory */ + delete [] colorIndex; + delete [] line; + delete [] srcp; +} + + +void FPCXTexture::ReadPCX8bits (BYTE *dst, FileReader & lump, PCXHeader *hdr) +{ + int rle_count = 0, rle_value = 0; + int y, bytes; + + BYTE * srcp = new BYTE[lump.GetLength() - sizeof(PCXHeader)]; + lump.Read(srcp, lump.GetLength() - sizeof(PCXHeader)); + BYTE * src = srcp; + + for (y = 0; y < Height; ++y) + { + BYTE * ptr = &dst[y * Width]; + + bytes = hdr->bytesPerScanLine; + while (bytes--) + { + if (rle_count == 0) + { + if( (rle_value = *src++) < 0xc0) + { + rle_count = 1; + } + else + { + rle_count = rle_value - 0xc0; + rle_value = *src++; + } + } + + rle_count--; + *ptr++ = rle_value; + } + } + delete [] srcp; +} + + +void FPCXTexture::ReadPCX24bits (BYTE *dst, FileReader & lump, PCXHeader *hdr, int planes) +{ + int rle_count = 0, rle_value = 0; + int y, c; + int bytes; + + BYTE * srcp = new BYTE[lump.GetLength() - sizeof(PCXHeader)]; + lump.Read(srcp, lump.GetLength() - sizeof(PCXHeader)); + BYTE * src = srcp; + + for (y = 0; y < Height; ++y) + { + /* for each color plane */ + for (c = 0; c < planes; ++c) + { + BYTE * ptr = &dst[y * Width * planes]; + bytes = hdr->bytesPerScanLine; + + while (bytes--) + { + if (rle_count == 0) + { + if( (rle_value = *src++) < 0xc0) + { + rle_count = 1; + } + else + { + rle_count = rle_value - 0xc0; + rle_value = *src++; + } + } + + rle_count--; + ptr[c] = (BYTE)rle_value; + ptr += planes; + } + } + } + delete [] srcp; +} + +void FPCXTexture::MakeTexture() +{ + BYTE PaletteMap[256]; + PCXHeader header; + int bitcount; + + FWadLump lump = Wads.OpenLumpNum(SourceLump); + + lump.Read(&header, sizeof(header)); + + bitcount = header.bitsPerPixel * header.numColorPlanes; + Pixels = new BYTE[Width*Height]; + + if (bitcount < 24) + { + if (bitcount < 8) + { + for (int i=0;i<16;i++) + { + PaletteMap[i] = ColorMatcher.Pick(header.palette[i*3],header.palette[i*3+1],header.palette[i*3+2]); + } + + switch (bitcount) + { + default: + case 1: + ReadPCX1bit (Pixels, lump, &header); + break; + + case 4: + ReadPCX4bits (Pixels, lump, &header); + break; + } + } + else if (bitcount == 8) + { + BYTE c; + lump.Seek(-769, SEEK_END); + lump >> c; + if (c !=0x0c) memcpy(PaletteMap, GrayMap, 256); // Fallback for files without palette + else for(int i=0;i<256;i++) + { + BYTE r,g,b; + lump >> r >> g >> b; + PaletteMap[i] = ColorMatcher.Pick(r,g,b); + } + lump.Seek(sizeof(header), SEEK_SET); + ReadPCX8bits (Pixels, lump, &header); + } + if (Width == Height) + { + FlipSquareBlockRemap(Pixels, Width, Height, PaletteMap); + } + else + { + BYTE *newpix = new BYTE[Width*Height]; + FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, PaletteMap); + BYTE *oldpix = Pixels; + Pixels = newpix; + delete[] oldpix; + } + } + else + { + BYTE * buffer = new BYTE[Width*Height * 3]; + BYTE * row = buffer; + ReadPCX24bits (buffer, lump, &header, 3); + for(int y=0; y>3][row[1]>>3][row[2]>>3]; + row+=3; + } + } + delete [] buffer; + } +} + diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 3bebcb0c1..f755544a2 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -1,5 +1,5 @@ /* -** pmgtexture.cpp +** pngtexture.cpp ** Texture class for PNG images ** **--------------------------------------------------------------------------- diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 81674fd9a..650271147 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -68,6 +68,7 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype) { FPNGTexture::Check, FPNGTexture::Create, FTexture::TEX_Any }, { FJPEGTexture::Check, FJPEGTexture::Create, FTexture::TEX_Any }, { FTGATexture::Check, FTGATexture::Create, FTexture::TEX_Any }, + { FPCXTexture::Check, FPCXTexture::Create, FTexture::TEX_Any }, { FRawPageTexture::Check, FRawPageTexture::Create, FTexture::TEX_MiscPatch }, { FFlatTexture::Check, FFlatTexture::Create, FTexture::TEX_Flat }, { FPatchTexture::Check, FPatchTexture::Create, FTexture::TEX_Any }, diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 244af2e86..b0d202d98 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -1,5 +1,5 @@ /* -** pmgtexture.cpp +** tgatexture.cpp ** Texture class for TGA images ** **--------------------------------------------------------------------------- @@ -40,28 +40,6 @@ #include "templates.h" - -#pragma pack(1) - -struct TGAHeader -{ - BYTE id_len; - BYTE has_cm; - BYTE img_type; - SWORD cm_first; - SWORD cm_length; - BYTE cm_size; - - SWORD x_origin; - SWORD y_origin; - SWORD width; - SWORD height; - BYTE bpp; - BYTE img_desc; -}; - -#pragma pack() - bool FTGATexture::Check(FileReader & data) { diff --git a/zdoom.vcproj b/zdoom.vcproj index f4c19b5e6..21ccecdff 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -4369,6 +4369,10 @@ RelativePath=".\src\textures\patchtexture.cpp" > + +