2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "ifilesystem.h"
26 typedef unsigned char byte;
31 #include "bytestreamutils.h"
34 =================================================================
38 =================================================================
43 unsigned char manufacturer;
44 unsigned char version;
45 unsigned char encoding;
46 unsigned char bits_per_pixel;
47 unsigned short xmin, ymin, xmax, ymax;
48 unsigned short hres, vres;
49 unsigned char palette[48];
50 unsigned char reserved;
51 unsigned char color_planes;
52 unsigned short bytes_per_line;
53 unsigned short palette_type;
54 unsigned char filler[58];
55 unsigned char data; // unbounded
70 inline void ByteStream_readPCXRLEPacket( PointerInputStream& inputStream, PCXRLEPacket& packet ){
72 inputStream.read( &d, 1 );
73 if ( ( d & 0xC0 ) == 0xC0 ) {
74 packet.length = d & 0x3F;
75 inputStream.read( &packet.data, 1 );
84 void LoadPCXBuff( byte* buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height ){
91 /* parse the PCX file */
93 PointerInputStream inputStream( buffer );
95 pcx.manufacturer = istream_read_byte( inputStream );
96 pcx.version = istream_read_byte( inputStream );
97 pcx.encoding = istream_read_byte( inputStream );
98 pcx.bits_per_pixel = istream_read_byte( inputStream );
99 pcx.xmin = istream_read_int16_le( inputStream );
100 pcx.ymin = istream_read_int16_le( inputStream );
101 pcx.xmax = istream_read_int16_le( inputStream );
102 pcx.ymax = istream_read_int16_le( inputStream );
103 pcx.hres = istream_read_int16_le( inputStream );
104 pcx.vres = istream_read_int16_le( inputStream );
105 inputStream.read( pcx.palette, 48 );
106 pcx.reserved = istream_read_byte( inputStream );
107 pcx.color_planes = istream_read_byte( inputStream );
108 pcx.bytes_per_line = istream_read_int16_le( inputStream );
109 pcx.palette_type = istream_read_int16_le( inputStream );
110 inputStream.read( pcx.filler, 58 );
113 if ( pcx.manufacturer != 0x0a
116 || pcx.bits_per_pixel != 8 ) {
121 *width = pcx.xmax + 1;
124 *height = pcx.ymax + 1;
131 out = (byte *)malloc( ( pcx.ymax + 1 ) * ( pcx.xmax + 1 ) );
136 /* RR2DO2: pcx fix */
137 lsize = pcx.color_planes * pcx.bytes_per_line;
139 /* go scanline by scanline */
140 for ( y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1 )
143 for ( x = 0; x <= pcx.xmax; )
147 ByteStream_readPCXRLEPacket( inputStream, packet );
149 while ( packet.length-- > 0 )
151 pix[ x++ ] = packet.data;
155 /* RR2DO2: discard any other data */
159 ByteStream_readPCXRLEPacket( inputStream, packet );
162 while ( packet.length-- > 0 )
169 if ( std::size_t( inputStream.get() - buffer ) > len ) {
174 *palette = (byte *)malloc( 768 );
175 memcpy( *palette, buffer + len - 768, 768 );
184 Image* LoadPCX32Buff( byte* buffer, std::size_t length ){
187 int i, c, p, width, height;
190 LoadPCXBuff( buffer, length, &pic8, &palette, &width, &height );
195 RGBAImage* image = new RGBAImage( width, height );
196 c = ( width ) * ( height );
197 pic32 = image->getRGBAPixels();
198 for ( i = 0; i < c; i++ )
201 pic32[0] = palette[p * 3];
202 pic32[1] = palette[p * 3 + 1];
203 pic32[2] = palette[p * 3 + 2];
214 Image* LoadPCX32( ArchiveFile& file ){
215 ScopedArchiveBuffer buffer( file );
216 return LoadPCX32Buff( buffer.buffer, buffer.length );