PCX.C 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. /*
  14. * $Source: f:/miner/source/2d/rcs/pcx.c $
  15. * $Revision: 1.6 $
  16. * $Author: john $
  17. * $Date: 1995/03/01 15:38:12 $
  18. *
  19. * Routines to read/write pcx images.
  20. *
  21. * $Log: pcx.c $
  22. * Revision 1.6 1995/03/01 15:38:12 john
  23. * Better ModeX support.
  24. *
  25. * Revision 1.5 1995/01/21 17:54:17 john
  26. * Added pcx reader for modes other than modex.
  27. *
  28. * Revision 1.4 1994/12/08 19:03:56 john
  29. * Made functions use cfile.
  30. *
  31. * Revision 1.3 1994/11/29 02:53:24 john
  32. * Added error messages; made call be more similiar to iff.
  33. *
  34. * Revision 1.2 1994/11/28 20:03:50 john
  35. * Added PCX functions.
  36. *
  37. * Revision 1.1 1994/11/28 19:57:56 john
  38. * Initial revision
  39. *
  40. *
  41. */
  42. #pragma off (unreferenced)
  43. static char rcsid[] = "$Id: pcx.c 1.6 1995/03/01 15:38:12 john Exp $";
  44. #pragma on (unreferenced)
  45. #include <stdlib.h>
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include "gr.h"
  49. #include "mem.h"
  50. #include "pcx.h"
  51. #include "cfile.h"
  52. /* PCX Header data type */
  53. typedef struct {
  54. ubyte Manufacturer;
  55. ubyte Version;
  56. ubyte Encoding;
  57. ubyte BitsPerPixel;
  58. short Xmin;
  59. short Ymin;
  60. short Xmax;
  61. short Ymax;
  62. short Hdpi;
  63. short Vdpi;
  64. ubyte ColorMap[16][3];
  65. ubyte Reserved;
  66. ubyte Nplanes;
  67. short BytesPerLine;
  68. ubyte filler[60];
  69. } PCXHeader;
  70. int pcx_read_bitmap( char * filename, grs_bitmap * bmp,int bitmap_type ,ubyte * palette )
  71. {
  72. PCXHeader header;
  73. CFILE * PCXfile;
  74. int i, row, col, count, xsize, ysize;
  75. ubyte data, *pixdata;
  76. PCXfile = cfopen( filename , "rb" );
  77. if ( !PCXfile )
  78. return PCX_ERROR_OPENING;
  79. // read 128 char PCX header
  80. if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) {
  81. cfclose( PCXfile );
  82. return PCX_ERROR_NO_HEADER;
  83. }
  84. // Is it a 256 color PCX file?
  85. if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) {
  86. cfclose( PCXfile );
  87. return PCX_ERROR_WRONG_VERSION;
  88. }
  89. // Find the size of the image
  90. xsize = header.Xmax - header.Xmin + 1;
  91. ysize = header.Ymax - header.Ymin + 1;
  92. if ( bitmap_type == BM_LINEAR ) {
  93. if ( bmp->bm_data == NULL ) {
  94. memset( bmp, 0, sizeof( grs_bitmap ) );
  95. bmp->bm_data = malloc( xsize * ysize );
  96. if ( bmp->bm_data == NULL ) {
  97. cfclose( PCXfile );
  98. return PCX_ERROR_MEMORY;
  99. }
  100. bmp->bm_w = bmp->bm_rowsize = xsize;
  101. bmp->bm_h = ysize;
  102. bmp->bm_type = bitmap_type;
  103. }
  104. }
  105. if ( bmp->bm_type == BM_LINEAR ) {
  106. for (row=0; row< ysize ; row++) {
  107. pixdata = &bmp->bm_data[bmp->bm_rowsize*row];
  108. for (col=0; col< xsize ; ) {
  109. if (cfread( &data, 1, 1, PCXfile )!=1 ) {
  110. cfclose( PCXfile );
  111. return PCX_ERROR_READING;
  112. }
  113. if ((data & 0xC0) == 0xC0) {
  114. count = data & 0x3F;
  115. if (cfread( &data, 1, 1, PCXfile )!=1 ) {
  116. cfclose( PCXfile );
  117. return PCX_ERROR_READING;
  118. }
  119. memset( pixdata, data, count );
  120. pixdata += count;
  121. col += count;
  122. } else {
  123. *pixdata++ = data;
  124. col++;
  125. }
  126. }
  127. }
  128. } else {
  129. for (row=0; row< ysize ; row++) {
  130. for (col=0; col< xsize ; ) {
  131. if (cfread( &data, 1, 1, PCXfile )!=1 ) {
  132. cfclose( PCXfile );
  133. return PCX_ERROR_READING;
  134. }
  135. if ((data & 0xC0) == 0xC0) {
  136. count = data & 0x3F;
  137. if (cfread( &data, 1, 1, PCXfile )!=1 ) {
  138. cfclose( PCXfile );
  139. return PCX_ERROR_READING;
  140. }
  141. for (i=0;i<count;i++)
  142. gr_bm_pixel( bmp, col+i, row, data );
  143. col += count;
  144. } else {
  145. gr_bm_pixel( bmp, col, row, data );
  146. col++;
  147. }
  148. }
  149. }
  150. }
  151. // Read the extended palette at the end of PCX file
  152. if ( palette != NULL ) {
  153. // Read in a character which should be 12 to be extended palette file
  154. if (cfread( &data, 1, 1, PCXfile )==1) {
  155. if ( data == 12 ) {
  156. if (cfread(palette,768, 1, PCXfile)!=1) {
  157. cfclose( PCXfile );
  158. return PCX_ERROR_READING;
  159. }
  160. for (i=0; i<768; i++ )
  161. palette[i] >>= 2;
  162. }
  163. } else {
  164. cfclose( PCXfile );
  165. return PCX_ERROR_NO_PALETTE;
  166. }
  167. }
  168. cfclose(PCXfile);
  169. return PCX_ERROR_NONE;
  170. }
  171. int pcx_write_bitmap( char * filename, grs_bitmap * bmp, ubyte * palette )
  172. {
  173. int retval;
  174. int i;
  175. ubyte data;
  176. PCXHeader header;
  177. FILE * PCXfile;
  178. memset( &header, 0, sizeof( PCXHeader ) );
  179. header.Manufacturer = 10;
  180. header.Encoding = 1;
  181. header.Nplanes = 1;
  182. header.BitsPerPixel = 8;
  183. header.Version = 5;
  184. header.Xmax = bmp->bm_w-1;
  185. header.Ymax = bmp->bm_h-1;
  186. header.BytesPerLine = bmp->bm_w;
  187. PCXfile = fopen( filename , "wb" );
  188. if ( !PCXfile )
  189. return PCX_ERROR_OPENING;
  190. if ( fwrite( &header, sizeof( PCXHeader ), 1, PCXfile ) != 1 ) {
  191. fclose( PCXfile );
  192. return PCX_ERROR_WRITING;
  193. }
  194. for (i=0; i<bmp->bm_h; i++ ) {
  195. if (!pcx_encode_line( &bmp->bm_data[bmp->bm_rowsize*i], bmp->bm_w, PCXfile )) {
  196. fclose( PCXfile );
  197. return PCX_ERROR_WRITING;
  198. }
  199. }
  200. // Mark an extended palette
  201. data = 12;
  202. if (fwrite( &data, 1, 1, PCXfile )!=1) {
  203. fclose( PCXfile );
  204. return PCX_ERROR_WRITING;
  205. }
  206. // Write the extended palette
  207. for (i=0; i<768; i++ )
  208. palette[i] <<= 2;
  209. retval = fwrite( palette, 768, 1, PCXfile );
  210. for (i=0; i<768; i++ )
  211. palette[i] >>= 2;
  212. if (retval !=1) {
  213. fclose( PCXfile );
  214. return PCX_ERROR_WRITING;
  215. }
  216. fclose( PCXfile );
  217. return PCX_ERROR_NONE;
  218. }
  219. // returns number of bytes written into outBuff, 0 if failed
  220. int pcx_encode_line(ubyte *inBuff, int inLen, FILE * fp)
  221. {
  222. ubyte this, last;
  223. int srcIndex, i;
  224. register int total;
  225. register ubyte runCount; // max single runlength is 63
  226. total = 0;
  227. last = *(inBuff);
  228. runCount = 1;
  229. for (srcIndex = 1; srcIndex < inLen; srcIndex++) {
  230. this = *(++inBuff);
  231. if (this == last) {
  232. runCount++; // it encodes
  233. if (runCount == 63) {
  234. if (!(i=pcx_encode_byte(last, runCount, fp)))
  235. return(0);
  236. total += i;
  237. runCount = 0;
  238. }
  239. } else { // this != last
  240. if (runCount) {
  241. if (!(i=pcx_encode_byte(last, runCount, fp)))
  242. return(0);
  243. total += i;
  244. }
  245. last = this;
  246. runCount = 1;
  247. }
  248. }
  249. if (runCount) { // finish up
  250. if (!(i=pcx_encode_byte(last, runCount, fp)))
  251. return 0;
  252. return total + i;
  253. }
  254. return total;
  255. }
  256. // subroutine for writing an encoded byte pair
  257. // returns count of bytes written, 0 if error
  258. int pcx_encode_byte(ubyte byt, ubyte cnt, FILE * fid)
  259. {
  260. if (cnt) {
  261. if ( (cnt==1) && (0xc0 != (0xc0 & byt)) ) {
  262. if(EOF == putc((int)byt, fid))
  263. return 0; // disk write error (probably full)
  264. return 1;
  265. } else {
  266. if(EOF == putc((int)0xC0 | cnt, fid))
  267. return 0; // disk write error
  268. if(EOF == putc((int)byt, fid))
  269. return 0; // disk write error
  270. return 2;
  271. }
  272. }
  273. return 0;
  274. }
  275. //text for error messges
  276. char pcx_error_messages[] = {
  277. "No error.\0"
  278. "Error opening file.\0"
  279. "Couldn't read PCX header.\0"
  280. "Unsupported PCX version.\0"
  281. "Error reading data.\0"
  282. "Couldn't find palette information.\0"
  283. "Error writing data.\0"
  284. };
  285. //function to return pointer to error message
  286. char *pcx_errormsg(int error_number)
  287. {
  288. char *p = pcx_error_messages;
  289. while (error_number--) {
  290. if (!p) return NULL;
  291. p += strlen(p)+1;
  292. }
  293. return p;
  294. }
  295.