pcxread.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "pcxread.hpp"
  2. #include "specs.hpp"
  3. struct PCX_header_type
  4. {
  5. char manufactururer,version,encoding,bits_per_pixel;
  6. short xmin,ymin,xmax,ymax,hres,vres;
  7. char palette[48];
  8. char reserved,color_planes;
  9. short bytes_per_line,palette_type;
  10. char filter[58];
  11. } PCX_header;
  12. int read_PCX_header(FILE *fp)
  13. {
  14. if (!fread(&PCX_header.manufactururer,1,1,fp)) return 0;
  15. if (!fread(&PCX_header.version,1,1,fp)) return 0;
  16. if (!fread(&PCX_header.encoding,1,1,fp)) return 0;
  17. if (!fread(&PCX_header.bits_per_pixel,1,1,fp)) return 0;
  18. PCX_header.xmin=read_short(fp);
  19. PCX_header.ymin=read_short(fp);
  20. PCX_header.xmax=read_short(fp);
  21. PCX_header.ymax=read_short(fp);
  22. PCX_header.hres=read_short(fp);
  23. PCX_header.vres=read_short(fp);
  24. if (!fread(PCX_header.palette,1,48,fp)) return 0;
  25. if (!fread(&PCX_header.reserved,1,1,fp)) return 0;
  26. if (!fread(&PCX_header.color_planes,1,1,fp)) return 0;
  27. PCX_header.bytes_per_line=read_short(fp);
  28. PCX_header.palette_type=read_short(fp);
  29. if (!fread(PCX_header.filter,1,58,fp)) return 0;
  30. return 1;
  31. }
  32. int write_PCX_header(FILE *fp)
  33. {
  34. if (!fwrite(&PCX_header.manufactururer,1,1,fp)) return 0;
  35. if (!fwrite(&PCX_header.version,1,1,fp)) return 0;
  36. if (!fwrite(&PCX_header.encoding,1,1,fp)) return 0;
  37. if (!fwrite(&PCX_header.bits_per_pixel,1,1,fp)) return 0;
  38. write_short(fp,PCX_header.xmin);
  39. write_short(fp,PCX_header.ymin);
  40. write_short(fp,PCX_header.xmax);
  41. write_short(fp,PCX_header.ymax);
  42. write_short(fp,PCX_header.hres);
  43. write_short(fp,PCX_header.vres);
  44. if (!fwrite(PCX_header.palette,1,48,fp)) return 0;
  45. if (!fwrite(&PCX_header.reserved,1,1,fp)) return 0;
  46. if (!fwrite(&PCX_header.color_planes,1,1,fp)) return 0;
  47. write_short(fp,PCX_header.bytes_per_line);
  48. write_short(fp,PCX_header.palette_type);
  49. if (!fwrite(PCX_header.filter,1,58,fp)) return 0;
  50. return 1;
  51. }
  52. PCX_type PCX_file_type(char *filename)
  53. {
  54. FILE *fp=fopen(filename,"rb");
  55. if (!fp)
  56. { set_error(imREAD_ERROR);
  57. return not_PCX;
  58. }
  59. if (!read_PCX_header(fp))
  60. {
  61. fclose(fp);
  62. set_error(imREAD_ERROR);
  63. return not_PCX;
  64. }
  65. fclose(fp);
  66. if (PCX_header.manufactururer!=10)
  67. return not_PCX;
  68. if (PCX_header.color_planes==3 && PCX_header.bits_per_pixel==8)
  69. return PCX_24;
  70. else if (PCX_header.color_planes==1 && PCX_header.bits_per_pixel==8)
  71. return PCX_8;
  72. else return not_PCX;
  73. }
  74. void read_PCX_line(FILE *fp, unsigned char *start, short skip, int width)
  75. {
  76. int c,n=0,i;
  77. do
  78. {
  79. c=fgetc(fp)&0xff;
  80. if ((c&0xc0)==0xc0)
  81. {
  82. i=c&0x3f;
  83. c=fgetc(fp);
  84. while (i--)
  85. {
  86. *start=c;
  87. start+=skip;
  88. n++;
  89. }
  90. }
  91. else
  92. {
  93. *start=c;
  94. start+=skip;
  95. n++;
  96. }
  97. } while (n<width);
  98. }
  99. image24 *read_PCX24(char *filename)
  100. {
  101. if (PCX_file_type(filename)!=PCX_24) return NULL;
  102. FILE *fp=fopen(filename,"rb");
  103. read_PCX_header(fp);
  104. image24 *im=new image24(PCX_header.xmax-PCX_header.xmin+1,
  105. PCX_header.ymax-PCX_header.ymin+1);
  106. int y;
  107. for (y=0;y<im->height();y++)
  108. {
  109. read_PCX_line(fp,im->scan_line(y),3,PCX_header.bytes_per_line);
  110. read_PCX_line(fp,im->scan_line(y)+1,3,PCX_header.bytes_per_line);
  111. read_PCX_line(fp,im->scan_line(y)+2,3,PCX_header.bytes_per_line);
  112. }
  113. fclose(fp);
  114. return im;
  115. }
  116. image *read_PCX(char *filename, palette *&pal)
  117. {
  118. if (PCX_file_type(filename)!=PCX_8) return NULL;
  119. FILE *fp=fopen(filename,"rb");
  120. read_PCX_header(fp);
  121. image *im=new image(PCX_header.xmax-PCX_header.xmin+1,
  122. PCX_header.ymax-PCX_header.ymin+1);
  123. int y;
  124. for (y=0;y<im->height();y++)
  125. read_PCX_line(fp,im->scan_line(y),1,PCX_header.bytes_per_line);
  126. unsigned char palette_confirm;
  127. if (!fread(&palette_confirm,1,1,fp) || palette_confirm!=12)
  128. {
  129. pal=new palette;
  130. pal->defaults();
  131. }
  132. else
  133. {
  134. pal=new palette;
  135. fread(pal->addr(),1,256*3,fp);
  136. }
  137. fclose(fp);
  138. return im;
  139. }
  140. void write_PCX(image *im, palette *pal, char *filename)
  141. {
  142. FILE *fp=fopen(filename,"wb");
  143. if (!fp)
  144. {
  145. set_error(imWRITE_ERROR);
  146. return ;
  147. }
  148. PCX_header.manufactururer=10;
  149. PCX_header.version=5;
  150. PCX_header.encoding=1;
  151. PCX_header.bits_per_pixel=8;
  152. PCX_header.xmin=0;
  153. PCX_header.ymin=0;
  154. PCX_header.xmax=im->width()-1;
  155. PCX_header.ymax=im->height()-1;
  156. PCX_header.hres=320;
  157. PCX_header.vres=200;
  158. PCX_header.reserved=0;
  159. PCX_header.color_planes=1;
  160. PCX_header.bytes_per_line=im->width();
  161. PCX_header.palette_type=0;
  162. memset(PCX_header.filter,0,58);
  163. if (!write_PCX_header(fp))
  164. {
  165. set_error( imWRITE_ERROR);
  166. return ;
  167. }
  168. int y,run_length,x;
  169. unsigned char *sl,code;
  170. for (y=0;y<im->height();y++)
  171. {
  172. sl=im->scan_line(y);
  173. for (x=0;x<im->width();)
  174. {
  175. run_length=1;
  176. while (x+run_length<im->width() && sl[x]==sl[x+run_length])
  177. run_length++;
  178. if (run_length==1 && sl[x]<64)
  179. fputc(sl[x],fp);
  180. else
  181. {
  182. if (run_length>=64)
  183. run_length=63;
  184. code=0xc0 | run_length;
  185. fputc(code,fp);
  186. fputc(sl[x],fp);
  187. }
  188. x+=run_length;
  189. }
  190. }
  191. fputc(12,fp); // note that there is a palette attached
  192. fwrite(pal->addr(),1,256*3,fp);
  193. fclose(fp);
  194. }