pcx.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. Copyright (C) 1999-2006 Id Software, Inc. and contributors.
  3. For a list of contributors, see the accompanying CONTRIBUTORS file.
  4. This file is part of GtkRadiant.
  5. GtkRadiant is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. GtkRadiant is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GtkRadiant; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #include "pcx.h"
  18. #include "ifilesystem.h"
  19. typedef unsigned char byte;
  20. #include <stdlib.h>
  21. #include "imagelib.h"
  22. #include "bytestreamutils.h"
  23. /*
  24. =================================================================
  25. PCX LOADING
  26. =================================================================
  27. */
  28. typedef struct
  29. {
  30. unsigned char manufacturer;
  31. unsigned char version;
  32. unsigned char encoding;
  33. unsigned char bits_per_pixel;
  34. unsigned short xmin, ymin, xmax, ymax;
  35. unsigned short hres, vres;
  36. unsigned char palette[48];
  37. unsigned char reserved;
  38. unsigned char color_planes;
  39. unsigned short bytes_per_line;
  40. unsigned short palette_type;
  41. unsigned char filler[58];
  42. unsigned char data; // unbounded
  43. } pcx_t;
  44. /*
  45. ==============
  46. LoadPCX
  47. ==============
  48. */
  49. struct PCXRLEPacket
  50. {
  51. byte data;
  52. int length;
  53. };
  54. inline void ByteStream_readPCXRLEPacket(PointerInputStream& inputStream, PCXRLEPacket& packet)
  55. {
  56. byte d;
  57. inputStream.read(&d, 1);
  58. if((d & 0xC0) == 0xC0)
  59. {
  60. packet.length = d & 0x3F;
  61. inputStream.read(&packet.data, 1);
  62. }
  63. else
  64. {
  65. packet.length = 1;
  66. packet.data = d;
  67. }
  68. }
  69. void LoadPCXBuff(byte* buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height )
  70. {
  71. *pic = 0;
  72. pcx_t pcx;
  73. int x, y, lsize;
  74. byte *out, *pix;
  75. /* parse the PCX file */
  76. PointerInputStream inputStream(buffer);
  77. pcx.manufacturer = istream_read_byte(inputStream);
  78. pcx.version = istream_read_byte(inputStream);
  79. pcx.encoding = istream_read_byte(inputStream);
  80. pcx.bits_per_pixel = istream_read_byte(inputStream);
  81. pcx.xmin = istream_read_int16_le(inputStream);
  82. pcx.ymin = istream_read_int16_le(inputStream);
  83. pcx.xmax = istream_read_int16_le(inputStream);
  84. pcx.ymax = istream_read_int16_le(inputStream);
  85. pcx.hres = istream_read_int16_le(inputStream);
  86. pcx.vres = istream_read_int16_le(inputStream);
  87. inputStream.read(pcx.palette, 48);
  88. pcx.reserved = istream_read_byte(inputStream);
  89. pcx.color_planes = istream_read_byte(inputStream);
  90. pcx.bytes_per_line = istream_read_int16_le(inputStream);
  91. pcx.palette_type = istream_read_int16_le(inputStream);
  92. inputStream.read(pcx.filler, 58);
  93. if (pcx.manufacturer != 0x0a
  94. || pcx.version != 5
  95. || pcx.encoding != 1
  96. || pcx.bits_per_pixel != 8)
  97. return;
  98. if (width)
  99. *width = pcx.xmax+1;
  100. if (height)
  101. *height = pcx.ymax+1;
  102. if (!pic)
  103. return;
  104. out = (byte *)malloc ( (pcx.ymax+1) * (pcx.xmax+1) );
  105. *pic = out;
  106. pix = out;
  107. /* RR2DO2: pcx fix */
  108. lsize = pcx.color_planes * pcx.bytes_per_line;
  109. /* go scanline by scanline */
  110. for( y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1 )
  111. {
  112. /* do a scanline */
  113. for( x=0; x <= pcx.xmax; )
  114. {
  115. /* RR2DO2 */
  116. PCXRLEPacket packet;
  117. ByteStream_readPCXRLEPacket(inputStream, packet);
  118. while(packet.length-- > 0)
  119. {
  120. pix[ x++ ] = packet.data;
  121. }
  122. }
  123. /* RR2DO2: discard any other data */
  124. PCXRLEPacket packet;
  125. while( x < lsize )
  126. {
  127. ByteStream_readPCXRLEPacket(inputStream, packet);
  128. x++;
  129. }
  130. while( packet.length-- > 0 )
  131. {
  132. x++;
  133. }
  134. }
  135. /* validity check */
  136. if( std::size_t(inputStream.get() - buffer) > len)
  137. {
  138. *pic = 0;
  139. }
  140. if (palette)
  141. {
  142. *palette = (byte *)malloc(768);
  143. memcpy (*palette, buffer + len - 768, 768);
  144. }
  145. }
  146. /*
  147. ==============
  148. LoadPCX32
  149. ==============
  150. */
  151. Image* LoadPCX32Buff(byte* buffer, std::size_t length)
  152. {
  153. byte *palette;
  154. byte *pic8;
  155. int i, c, p, width, height;
  156. byte *pic32;
  157. LoadPCXBuff(buffer, length, &pic8, &palette, &width, &height);
  158. if (!pic8)
  159. {
  160. return 0;
  161. }
  162. RGBAImage* image = new RGBAImage(width, height);
  163. c = (width) * (height);
  164. pic32 = image->getRGBAPixels();
  165. for (i = 0; i < c; i++)
  166. {
  167. p = pic8[i];
  168. pic32[0] = palette[p * 3];
  169. pic32[1] = palette[p * 3 + 1];
  170. pic32[2] = palette[p * 3 + 2];
  171. pic32[3] = 255;
  172. pic32 += 4;
  173. }
  174. free (pic8);
  175. free (palette);
  176. return image;
  177. }
  178. Image* LoadPCX32(ArchiveFile& file)
  179. {
  180. ScopedArchiveBuffer buffer(file);
  181. return LoadPCX32Buff(buffer.buffer, buffer.length);
  182. }