123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /*
- Copyright (C) 1999-2006 Id Software, Inc. and contributors.
- For a list of contributors, see the accompanying CONTRIBUTORS file.
- This file is part of GtkRadiant.
- GtkRadiant is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- GtkRadiant is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GtkRadiant; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "pcx.h"
- #include "ifilesystem.h"
- typedef unsigned char byte;
- #include <stdlib.h>
- #include "imagelib.h"
- #include "bytestreamutils.h"
- /*
- =================================================================
- PCX LOADING
- =================================================================
- */
- typedef struct
- {
- unsigned char manufacturer;
- unsigned char version;
- unsigned char encoding;
- unsigned char bits_per_pixel;
- unsigned short xmin, ymin, xmax, ymax;
- unsigned short hres, vres;
- unsigned char palette[48];
- unsigned char reserved;
- unsigned char color_planes;
- unsigned short bytes_per_line;
- unsigned short palette_type;
- unsigned char filler[58];
- unsigned char data; // unbounded
- } pcx_t;
- /*
- ==============
- LoadPCX
- ==============
- */
- struct PCXRLEPacket
- {
- byte data;
- int length;
- };
- inline void ByteStream_readPCXRLEPacket(PointerInputStream& inputStream, PCXRLEPacket& packet)
- {
- byte d;
- inputStream.read(&d, 1);
- if((d & 0xC0) == 0xC0)
- {
- packet.length = d & 0x3F;
- inputStream.read(&packet.data, 1);
- }
- else
- {
- packet.length = 1;
- packet.data = d;
- }
- }
- void LoadPCXBuff(byte* buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height )
- {
- *pic = 0;
- pcx_t pcx;
- int x, y, lsize;
- byte *out, *pix;
- /* parse the PCX file */
- PointerInputStream inputStream(buffer);
-
- pcx.manufacturer = istream_read_byte(inputStream);
- pcx.version = istream_read_byte(inputStream);
- pcx.encoding = istream_read_byte(inputStream);
- pcx.bits_per_pixel = istream_read_byte(inputStream);
- pcx.xmin = istream_read_int16_le(inputStream);
- pcx.ymin = istream_read_int16_le(inputStream);
- pcx.xmax = istream_read_int16_le(inputStream);
- pcx.ymax = istream_read_int16_le(inputStream);
- pcx.hres = istream_read_int16_le(inputStream);
- pcx.vres = istream_read_int16_le(inputStream);
- inputStream.read(pcx.palette, 48);
- pcx.reserved = istream_read_byte(inputStream);
- pcx.color_planes = istream_read_byte(inputStream);
- pcx.bytes_per_line = istream_read_int16_le(inputStream);
- pcx.palette_type = istream_read_int16_le(inputStream);
- inputStream.read(pcx.filler, 58);
-
- if (pcx.manufacturer != 0x0a
- || pcx.version != 5
- || pcx.encoding != 1
- || pcx.bits_per_pixel != 8)
- return;
- if (width)
- *width = pcx.xmax+1;
- if (height)
- *height = pcx.ymax+1;
- if (!pic)
- return;
- out = (byte *)malloc ( (pcx.ymax+1) * (pcx.xmax+1) );
- *pic = out;
- pix = out;
-
- /* RR2DO2: pcx fix */
- lsize = pcx.color_planes * pcx.bytes_per_line;
-
- /* go scanline by scanline */
- for( y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1 )
- {
- /* do a scanline */
- for( x=0; x <= pcx.xmax; )
- {
- /* RR2DO2 */
- PCXRLEPacket packet;
- ByteStream_readPCXRLEPacket(inputStream, packet);
-
- while(packet.length-- > 0)
- {
- pix[ x++ ] = packet.data;
- }
- }
- /* RR2DO2: discard any other data */
- PCXRLEPacket packet;
- while( x < lsize )
- {
- ByteStream_readPCXRLEPacket(inputStream, packet);
- x++;
- }
- while( packet.length-- > 0 )
- {
- x++;
- }
- }
-
- /* validity check */
- if( std::size_t(inputStream.get() - buffer) > len)
- {
- *pic = 0;
- }
- if (palette)
- {
- *palette = (byte *)malloc(768);
- memcpy (*palette, buffer + len - 768, 768);
- }
- }
- /*
- ==============
- LoadPCX32
- ==============
- */
- Image* LoadPCX32Buff(byte* buffer, std::size_t length)
- {
- byte *palette;
- byte *pic8;
- int i, c, p, width, height;
- byte *pic32;
- LoadPCXBuff(buffer, length, &pic8, &palette, &width, &height);
- if (!pic8)
- {
- return 0;
- }
- RGBAImage* image = new RGBAImage(width, height);
- c = (width) * (height);
- pic32 = image->getRGBAPixels();
- for (i = 0; i < c; i++)
- {
- p = pic8[i];
- pic32[0] = palette[p * 3];
- pic32[1] = palette[p * 3 + 1];
- pic32[2] = palette[p * 3 + 2];
- pic32[3] = 255;
- pic32 += 4;
- }
- free (pic8);
- free (palette);
- return image;
- }
- Image* LoadPCX32(ArchiveFile& file)
- {
- ScopedArchiveBuffer buffer(file);
- return LoadPCX32Buff(buffer.buffer, buffer.length);
- }
|