PageRenderTime 54ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/Pristine/CROP/PCX.C

http://github.com/AnimatorPro/Animator-Pro
C | 449 lines | 418 code | 29 blank | 2 comment | 73 complexity | d802848773cd4d53da499f12796b85d2 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /* pcx.c - Stuff to handle PC-PaintBrush (.PCX) files */
  2. #include "jimk.h"
  3. #include "crop.h"
  4. #include "pcx.str"
  5. struct pcx_header
  6. {
  7. UBYTE magic, version, encode, bitpx;
  8. WORD x1,y1,x2,y2;
  9. WORD cardw, cardh;
  10. UBYTE palette[48];
  11. UBYTE vmode, nplanes;
  12. WORD bpl; /* bytes per line of piccie */
  13. UBYTE pad[60];
  14. };
  15. static struct pcx_header pcxh;
  16. static int pcx_err = -1;
  17. static char *pcx_name;
  18. static struct bfile pcx_bf;
  19. static int pcw, pch;
  20. static UBYTE *over;
  21. static UBYTE *buf;
  22. static UBYTE with_cmap;
  23. static int over_count;
  24. static UBYTE default_pcx_cmap[] =
  25. {
  26. 0x00, 0x00, 0x00,
  27. 0x00, 0x00, 0xaa,
  28. 0x00, 0xaa, 0x00,
  29. 0x00, 0xaa, 0xaa,
  30. 0xaa, 0x00, 0x00,
  31. 0xaa, 0x00, 0xaa,
  32. 0xaa, 0xaa, 0x00,
  33. 0xaa, 0xaa, 0xaa,
  34. 0x55, 0x55, 0x55,
  35. 0x55, 0x55, 0xff,
  36. 0x55, 0xff, 0x55,
  37. 0x55, 0xff, 0xff,
  38. 0xff, 0x55, 0x55,
  39. 0xff, 0x55, 0xff,
  40. 0xff, 0xff, 0x55,
  41. 0xff, 0xff, 0xff
  42. };
  43. static UBYTE bwcmap[] = {0,0,0,0x3f,0x3f,0x3f,};
  44. static
  45. pctrunc()
  46. {
  47. truncated(pcx_name);
  48. }
  49. static char *wpcx_lines[] =
  50. {
  51. pcx_100 /* "This isn't a type of .PCX file" */,
  52. pcx_101 /* "Converter understands. Possibly the" */,
  53. pcx_102 /* "file is damaged or a new revision." */,
  54. NULL,
  55. };
  56. static
  57. weird_pcx()
  58. {
  59. continu_box(wpcx_lines);
  60. }
  61. static read_palette_256(cmap)
  62. UBYTE *cmap;
  63. {
  64. int i;
  65. int c;
  66. if (bgetbyte(&pcx_bf) != 12)
  67. {
  68. weird_pcx();
  69. }
  70. i = 256*3;
  71. while (--i >= 0)
  72. {
  73. if ((c = bgetbyte(&pcx_bf)) < 0)
  74. {
  75. pctrunc();
  76. return(0);
  77. }
  78. *cmap++ = (c>>2);
  79. }
  80. return(1);
  81. }
  82. static
  83. pcx_line()
  84. {
  85. int i, lpos;
  86. UBYTE *p;
  87. register int count;
  88. UBYTE data;
  89. /* first deal with any overflow from last line */
  90. copy_bytes(over, buf, over_count);
  91. lpos = pcxh.bpl - over_count;
  92. p = buf + over_count;
  93. while (lpos > 0)
  94. {
  95. if ((count = bgetbyte(&pcx_bf)) < 0)
  96. {
  97. pctrunc();
  98. return(0);
  99. }
  100. if ((count & 0xc0) == 0xc0)
  101. {
  102. count &= 0x3f;
  103. data = bgetbyte(&pcx_bf);
  104. lpos -= count;
  105. while (--count >= 0)
  106. *p++ = data;
  107. }
  108. else
  109. {
  110. *p++ = count;
  111. lpos -= 1;
  112. }
  113. }
  114. over_count = -lpos;
  115. return(1);
  116. }
  117. static
  118. bits2_to_bytes(in, out, w, omask)
  119. UBYTE *in, *out;
  120. int w;
  121. UBYTE omask;
  122. {
  123. int k;
  124. UBYTE imask;
  125. UBYTE omask2;
  126. UBYTE c;
  127. omask2 = omask<<1;
  128. while (w > 0)
  129. {
  130. imask = 0x80;
  131. k = 4;
  132. if (k > w)
  133. k = w;
  134. c = *in++;
  135. while (--k >= 0)
  136. {
  137. if (c&imask)
  138. *out |= omask;
  139. imask >>= 1;
  140. if (c&imask)
  141. *out |= omask2;
  142. out += 1;
  143. imask >>= 1;
  144. }
  145. w -= 4;
  146. }
  147. }
  148. static
  149. pcx_to_bap(p,omask)
  150. UBYTE *p;
  151. int omask;
  152. {
  153. if (pcxh.bitpx == 1)
  154. {
  155. bits_to_bytes(buf, p, pcw, omask);
  156. }
  157. else if (pcxh.bitpx == 2)
  158. {
  159. bits2_to_bytes(buf,p,pcw, omask);
  160. }
  161. else if (pcxh.bitpx == 8)
  162. {
  163. copy_bytes(buf,p,pcw);
  164. }
  165. }
  166. static
  167. init_pcx_line()
  168. {
  169. over_count = 0;
  170. if ((buf=begmem(pcxh.bpl + 64)) == NULL)
  171. return(0);
  172. over = buf + pcxh.bpl;
  173. return(1);
  174. }
  175. static
  176. unpack_pcx()
  177. {
  178. int y;
  179. UBYTE *p;
  180. int dbpr;
  181. int ok;
  182. int d;
  183. int omask;
  184. if (!init_pcx_line())
  185. return(0);
  186. y = pch;
  187. p = pic_cel->p;
  188. dbpr = pic_cel->bpr;
  189. ok = 1;
  190. while (--y >= 0)
  191. {
  192. zero_bytes(p, dbpr);
  193. d = pcxh.nplanes;
  194. omask = 1;
  195. while (--d >= 0)
  196. {
  197. if (!pcx_line())
  198. {
  199. ok = 0;
  200. goto OUT;
  201. }
  202. if (is_bitplane)
  203. {
  204. copy_bytes(buf, p, dbpr);
  205. }
  206. else
  207. {
  208. pcx_to_bap(p, omask);
  209. }
  210. omask <<= 1;
  211. }
  212. p = norm_pointer(p+dbpr);
  213. }
  214. OUT:
  215. freemem(buf);
  216. return(ok);
  217. }
  218. static
  219. trans_pal(s,d,count)
  220. UBYTE *s, *d;
  221. int count;
  222. {
  223. count *= 3;
  224. while (--count >= 0)
  225. *d++ = (*s++)>>2;
  226. }
  227. open_pcx(name)
  228. char *name;
  229. {
  230. Vcel *(*alloc_func)();
  231. if (pcx_err != -1)
  232. {
  233. continu_line(pcx_103 /* "Already opened PCX" */);
  234. return(0);
  235. }
  236. pcx_name = name;
  237. if (!bopen(name, &pcx_bf))
  238. {
  239. cant_find(name);
  240. return(0);
  241. }
  242. if (bread(&pcx_bf, &pcxh, sizeof(pcxh)) != sizeof(pcxh))
  243. {
  244. pctrunc();
  245. goto BADOUT;
  246. }
  247. if (pcxh.encode != 1)
  248. {
  249. weird_pcx();
  250. goto BADOUT;
  251. }
  252. switch (pcxh.version)
  253. {
  254. case 0:
  255. pcxh.nplanes = 1;
  256. with_cmap = 0;
  257. break;
  258. case 2:
  259. with_cmap = 1;
  260. break;
  261. case 3:
  262. with_cmap = 0;
  263. break;
  264. case 5:
  265. with_cmap = 1;
  266. break;
  267. default:
  268. weird_pcx();
  269. goto BADOUT;
  270. }
  271. if (pcxh.nplanes*pcxh.bitpx == 1)
  272. {
  273. is_bitplane = 1;
  274. }
  275. if (with_cmap)
  276. trans_pal(pcxh.palette, vf.cmap, 16);
  277. else
  278. {
  279. if (is_bitplane) /* one bit plane no cmap, use b&w */
  280. copy_bytes(bwcmap,vf.cmap,6);
  281. else /* use standard vga thingie */
  282. trans_pal(default_pcx_cmap, vf.cmap, 16);
  283. }
  284. switch (pcxh.bitpx)
  285. {
  286. case 1:
  287. case 2:
  288. case 8:
  289. break;
  290. default:
  291. weird_pcx();
  292. goto BADOUT;
  293. }
  294. pcw = pcxh.x2 - pcxh.x1 + 1;
  295. pch = pcxh.y2 - pcxh.y1 + 1;
  296. free_cel(pic_cel);
  297. if (is_bitplane)
  298. {
  299. if ((pic_cel = alloc_bcel(pcw,pch,pcxh.x1,pcxh.y1)) == 0)
  300. goto BADOUT;
  301. }
  302. else
  303. {
  304. if ((pic_cel = alloc_cel(pcw,pch,pcxh.x1,pcxh.y1)) == 0)
  305. goto BADOUT;
  306. }
  307. if (!unpack_pcx())
  308. goto BADOUT;
  309. if (pcxh.bitpx == 8 && with_cmap)
  310. {
  311. if (!read_palette_256(vf.cmap))
  312. goto BADOUT;
  313. }
  314. copy_cmap(vf.cmap, pic_cel->cmap);
  315. see_cmap();
  316. pcx_err = 0;
  317. return(1);
  318. BADOUT:
  319. close_pcx();
  320. return(0);
  321. }
  322. close_pcx()
  323. {
  324. free_cel(pic_cel);
  325. pic_cel = NULL;
  326. bclose(&pcx_bf);
  327. pcx_err = -1;
  328. }
  329. count_pcx()
  330. {
  331. if (pcx_err)
  332. return(0);
  333. return(1);
  334. }
  335. speed_pcx()
  336. {
  337. return(4);
  338. }
  339. start_pcx()
  340. {
  341. return(next_pcx());
  342. }
  343. next_pcx()
  344. {
  345. if (pcx_err)
  346. return(0);
  347. tile_s_cel(pic_cel);
  348. return(1);
  349. }
  350. scale_pcx(w,h)
  351. int w,h;
  352. {
  353. UBYTE *msbuf;
  354. UBYTE *mdbuf;
  355. int i;
  356. int ok = 0;
  357. struct bfile outf;
  358. int bpr;
  359. char lbuf[40];
  360. if (!is_bitplane)
  361. {
  362. return(scale_pic_cel(w,h));
  363. }
  364. if (init_pcx_line())
  365. {
  366. if (bcreate("grey", &outf))
  367. {
  368. free_cel(pic_cel);
  369. pic_cel = NULL;
  370. if ((msbuf = begmem(pcw)) != NULL)
  371. {
  372. if ((mdbuf = begmem(w)) != NULL)
  373. {
  374. bseek(&pcx_bf, (long)sizeof(pcxh), SEEK_START);
  375. for (i=0; i<pch; i++)
  376. {
  377. if (i%10 == 0)
  378. {
  379. sprintf(lbuf, pcx_105 /* "%3d of %d" */, i, pch);
  380. stext(lbuf, 0, 0, sblack, swhite);
  381. }
  382. if (!pcx_line())
  383. goto ELOOP;
  384. zero_bytes(msbuf, pcw);
  385. bits_to_bytes(buf, msbuf, pcw, 0x3f);
  386. iscale(msbuf, pcw, mdbuf, w);
  387. if (bwrite(&outf, mdbuf, w) != w)
  388. goto ELOOP;
  389. }
  390. ok = 1;
  391. ELOOP:
  392. freemem(mdbuf);
  393. }
  394. freemem(msbuf);
  395. }
  396. bclose(&outf);
  397. }
  398. if (ok)
  399. {
  400. sprintf(buf, pcx_106 /* " 0 of %d" */, w);
  401. stext(buf, 0, 10, sblack, swhite);
  402. if (yscale_file("grey", w, pch, h))
  403. {
  404. if ((pic_cel = alloc_cel(w,h,0,0)) != NULL)
  405. {
  406. if (read_gulp("grey", pic_cel->p,
  407. (long)pic_cel->bpr * pic_cel->h))
  408. {
  409. grey_cmap(vf.cmap);
  410. copy_cmap(vf.cmap, pic_cel->cmap);
  411. see_cmap();
  412. is_bitplane = 0;
  413. }
  414. }
  415. }
  416. }
  417. jdelete("grey");
  418. }
  419. return(ok);
  420. }