PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Pristine/CROP/SCALE.C

http://github.com/AnimatorPro/Animator-Pro
C | 514 lines | 464 code | 40 blank | 10 comment | 73 complexity | faceb82415e6bb107bee7d59b746e6d8 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /* scale.c - Do a nice pixel-averaging scale-up/scale-down */
  2. #include "jimk.h"
  3. #include "crop.h"
  4. #include "scale.str"
  5. #define WHOLESCALE 256
  6. struct bfile rgb_files[3];
  7. char *rgb_names[3] =
  8. {
  9. "red",
  10. "green",
  11. "blue",
  12. };
  13. kill_rgb_files()
  14. {
  15. int i;
  16. for (i=0;i<3;i++)
  17. jdelete(rgb_names[i]);
  18. }
  19. open_rgb_files()
  20. {
  21. int i;
  22. for (i=0; i<3; i++)
  23. {
  24. if (!bopen(rgb_names[i], rgb_files+i))
  25. {
  26. cant_find(rgb_names[i]);
  27. close_rgb_files();
  28. return(0);
  29. }
  30. }
  31. return(1);
  32. }
  33. create_rgb_files()
  34. {
  35. int i;
  36. for (i=0; i<3; i++)
  37. {
  38. if (!bcreate(rgb_names[i], rgb_files+i))
  39. {
  40. cant_create(rgb_names[i]);
  41. close_rgb_files();
  42. return(0);
  43. }
  44. }
  45. return(1);
  46. }
  47. close_rgb_files()
  48. {
  49. int i;
  50. for (i=0; i<3; i++)
  51. bclose(rgb_files+i);
  52. }
  53. iscale(s, sct, d, dct)
  54. UBYTE *s, *d;
  55. int sct, dct;
  56. {
  57. if (sct > dct) /* going to do some averaging */
  58. {
  59. int i;
  60. int j, jend, lj;
  61. long lasts, ldiv;
  62. long acc, div;
  63. long t1,t2;
  64. ldiv = WHOLESCALE;
  65. lasts = s[0];
  66. lj = 0;
  67. for (i=0; i<dct; i++)
  68. {
  69. acc = lasts*ldiv;
  70. div = ldiv;
  71. t1 = (i+1)*(long)sct;
  72. jend = t1/dct;
  73. for (j = lj+1; j<jend; j++)
  74. {
  75. acc += s[j]*WHOLESCALE;
  76. div += WHOLESCALE;
  77. }
  78. t2 = t1 - jend*(long)dct;
  79. lj = jend;
  80. lasts = s[lj];
  81. if (t2 == 0)
  82. {
  83. ldiv = WHOLESCALE;
  84. }
  85. else
  86. {
  87. ldiv = WHOLESCALE*t2/dct;
  88. div += ldiv;
  89. acc += lasts*ldiv;
  90. ldiv = WHOLESCALE-ldiv;
  91. }
  92. *d++ = acc/div;
  93. }
  94. }
  95. else if (dct == sct) /* they's the same */
  96. {
  97. while (--dct >= 0)
  98. *d++ = *s++;
  99. }
  100. else if (sct == 1)
  101. {
  102. while (--dct >= 0)
  103. *d++ = *s;
  104. }
  105. else/* going to do some interpolation */
  106. {
  107. int i;
  108. long t1;
  109. long p1;
  110. long err;
  111. int dct2;
  112. dct -= 1;
  113. sct -= 1;
  114. dct2 = dct/2;
  115. t1 = 0;
  116. for (i=0; i<=dct; i++)
  117. {
  118. p1 = t1/dct;
  119. err = t1 - p1*dct;
  120. if (err == 0)
  121. *d++ = s[p1];
  122. else
  123. *d++ = (s[p1]*(dct-err)+s[p1+1]*err+dct2)/dct;
  124. t1 += sct;
  125. }
  126. }
  127. }
  128. static line_to_3files(l, size, rgb, y)
  129. UBYTE *l;
  130. int size;
  131. int rgb, y;
  132. {
  133. int i;
  134. if (rgb == 0 && y%10 == 0)
  135. {
  136. char buf[30];
  137. sprintf(buf, "%3d", y);
  138. stext(buf, 0, 10, sblack, swhite);
  139. }
  140. if (bwrite(rgb_files + rgb, l, size) != size)
  141. {
  142. truncated(rgb_names[rgb]);
  143. return(0);
  144. }
  145. return(1);
  146. }
  147. /* basically look up a component of in into out through red component of
  148. color map */
  149. vga_to_red(in, out, w, cmap)
  150. UBYTE *in;
  151. UBYTE *out;
  152. int w;
  153. UBYTE *cmap;
  154. {
  155. while (--w >= 0)
  156. *out++ = cmap[3 * *in++];
  157. }
  158. get_column(s, d, w, h)
  159. UBYTE *s, *d;
  160. int w, h;
  161. {
  162. while (--h >= 0)
  163. {
  164. *d++ = *s;
  165. s = norm_pointer(s+w);
  166. }
  167. }
  168. put_column(s, d, w, h)
  169. UBYTE *s, *d;
  170. int w, h;
  171. {
  172. while (--h >= 0)
  173. {
  174. *d = *s++;
  175. d = norm_pointer(d+w);
  176. }
  177. }
  178. /* interpolate scale a byte-plane in memory in y dimension */
  179. scaley(inbytes, outbytes, inline, outline, w, oh, nh)
  180. UBYTE *inbytes, *outbytes; /* image and a place to put scaled copy */
  181. UBYTE *inline, *outline; /* buffers size oh and nh... */
  182. int w, oh, nh;
  183. {
  184. int i;
  185. char buf[50];
  186. for (i=0; i<w; i++)
  187. {
  188. get_column(inbytes++, inline, w, oh);
  189. iscale(inline, oh, outline, nh);
  190. put_column(outline, outbytes++, w, nh);
  191. if (i%10 == 0)
  192. {
  193. sprintf(buf, "%3d", i);
  194. stext(buf, 0, 10, sblack, swhite);
  195. }
  196. }
  197. }
  198. grey_cmap(c)
  199. UBYTE *c;
  200. {
  201. int i;
  202. int j;
  203. for (i=0; i<64; i++)
  204. {
  205. j = 1;
  206. while (--j >= 0)
  207. {
  208. *c++ = i;
  209. *c++ = i;
  210. *c++ = i;
  211. }
  212. }
  213. }
  214. yscale_file(name, w, oh, nh)
  215. char *name;
  216. int w, oh, nh;
  217. {
  218. UBYTE *inbytes;
  219. UBYTE *outbytes;
  220. Vcel *outcel;
  221. struct bfile bf;
  222. int ok = 0;
  223. long ibsize;
  224. UBYTE *inline, *outline;
  225. if (oh == nh)
  226. return(1);
  227. ibsize = w * (long)oh;
  228. if ((inbytes = lbegmem(ibsize)) == NULL)
  229. return(0);
  230. if ((outcel = alloc_cel(w,nh,0,0)) == NULL)
  231. {
  232. freemem(inbytes);
  233. return(0);
  234. }
  235. outbytes = outcel->p;
  236. if ((inline = begmem(oh)) != NULL)
  237. {
  238. if ((outline = begmem(nh)) != NULL)
  239. {
  240. if (read_gulp(name, inbytes, ibsize))
  241. {
  242. scaley(inbytes, outbytes, inline, outline, w, oh, nh);
  243. ok = write_gulp(name, outbytes, w * (long)nh);
  244. tile_cel(outcel);
  245. }
  246. freemem(outline);
  247. }
  248. freemem(inline);
  249. }
  250. freemem(inbytes);
  251. free_cel(outcel);
  252. return(ok);
  253. }
  254. scale_xdim_cel(cel, new_w, lineout)
  255. Vcel *cel;
  256. int new_w;
  257. Vector lineout;
  258. {
  259. int h;
  260. UBYTE *line_in;
  261. UBYTE *rgb_in;
  262. UBYTE *rgb_out;
  263. int i,j;
  264. int ok = 0;
  265. if ((rgb_in = begmem(cel->w)) == NULL)
  266. return(0);
  267. if ((rgb_out = begmem(new_w)) == NULL)
  268. {
  269. freemem(rgb_in);
  270. return(0);
  271. }
  272. line_in = cel->p;
  273. h = cel->h;
  274. for (j=0; j<h; j++)
  275. {
  276. for (i=0; i<3; i++)
  277. {
  278. vga_to_red(line_in, rgb_in, cel->w, cel->cmap+i);
  279. iscale(rgb_in, cel->w, rgb_out, new_w);
  280. if (!(*lineout)(rgb_out, new_w, i, j))
  281. goto OUT;
  282. }
  283. ok = 1;
  284. line_in = norm_pointer(line_in + cel->bpr);
  285. }
  286. OUT:
  287. freemem(rgb_in);
  288. freemem(rgb_out);
  289. return(ok);
  290. }
  291. scale_rgb_files(h, new_w, new_h)
  292. int h, new_w, new_h;
  293. {
  294. char buf[40];
  295. int i;
  296. int ok;
  297. /* now scale the ram-disk files y-wise */
  298. grey_cmap(vf.cmap);
  299. find_colors();
  300. see_cmap();
  301. for (i=0; i<3; i++)
  302. {
  303. sprintf(buf, scale_105 /* "Y-scale %s component " */, rgb_names[i]);
  304. stext(buf, 0, 0, sblack, swhite);
  305. sprintf(buf, scale_108 /* "%3d of %d" */, 0, new_w);
  306. stext(buf, 0, 10, sblack, swhite);
  307. if (!yscale_file(rgb_names[i], new_w, h, new_h))
  308. return(0);
  309. }
  310. /* now figure out the color map and load cel with that color map from
  311. the rgb files */
  312. if (!find_rgb_cmap(new_w, new_h, vf.cmap))
  313. return(0);
  314. if (!open_rgb_files())
  315. return(0);
  316. if (!make_bhash())
  317. return(0);
  318. ok = cel_with_cmap(new_w, new_h);
  319. free_bhash();
  320. close_rgb_files();
  321. if (!ok)
  322. {
  323. free_cel(pic_cel);
  324. pic_cel = NULL;
  325. return(0);
  326. }
  327. see_cmap();
  328. copy_cmap(vf.cmap, pic_cel->cmap);
  329. return(1);
  330. }
  331. static
  332. s_pic_cel(new_w, new_h)
  333. int new_w, new_h;
  334. {
  335. int h;
  336. int i, ok;
  337. char buf[120];
  338. if (create_rgb_files())
  339. {
  340. /* first scale it horizontally into 3 files in the ram-disk */
  341. h = pic_cel->h;
  342. sprintf(buf, scale_107 /* "X - scaling line" */, 0, h);
  343. stext(buf, 0, 00, sblack, swhite);
  344. sprintf(buf, scale_108 /* "%3d of %d" */, 0, h);
  345. stext(buf, 0, 10, sblack, swhite);
  346. ok = scale_xdim_cel(pic_cel, new_w, line_to_3files);
  347. close_rgb_files();
  348. if (!ok)
  349. return(0);
  350. free_cel(pic_cel);
  351. pic_cel = NULL;
  352. if (!scale_rgb_files(h, new_w, new_h))
  353. return(0);
  354. tile_cel(pic_cel);
  355. }
  356. return(1);
  357. }
  358. scale_pic_cel(w,h)
  359. int w, h;
  360. {
  361. int ok;
  362. ok = s_pic_cel(w,h);
  363. kill_rgb_files();
  364. return(ok);
  365. }
  366. static int scalew = XMAX, scaleh = YMAX;
  367. extern int dither;
  368. qscale()
  369. {
  370. char *bufs[8];
  371. char b1[30], b2[30], b3[30], b4[30];
  372. int choice;
  373. long r1,r2;
  374. int ouzx,ouzy; /* bad kludge to keep menus from moving... */
  375. ouzx = uzx;
  376. ouzy = uzy;
  377. for (;;)
  378. {
  379. uzx = ouzx;
  380. uzy = ouzy;
  381. /* make up strings for menu */
  382. sprintf(b1, scale_109 /* "Set Width %3d" */, scalew);
  383. bufs[0] = b1;
  384. sprintf(b2, scale_110 /* "Set Height %3d" */, scaleh);
  385. bufs[1] = b2;
  386. bufs[2] = scale_111 /* "Default 320x200" */;
  387. bufs[3] = scale_112 /* "Correct Aspect Ratio" */;
  388. sprintf(b3,
  389. scale_113 /* "Revert %3dx%3d" */, pic_cel->w, pic_cel->h);
  390. bufs[4] = b3;
  391. sprintf(b4, scale_114 /* "%s Dither" */, dither ? "*" : " ");
  392. bufs[5] = b4;
  393. bufs[6] = scale_117 /* "Render" */;
  394. bufs[7] = scale_118 /* "Exit Menu" */;
  395. if ((choice = qchoice(scale_119 /* "Scale..." */,
  396. bufs, Array_els(bufs))) == 0)
  397. break;
  398. switch (choice)
  399. {
  400. case 1:
  401. qreq_number(scale_120 /* "Set destination width" */,
  402. &scalew, 1, pic_cel->w);
  403. break;
  404. case 2:
  405. qreq_number(scale_121 /* "Set destination height" */,
  406. &scaleh, 1, pic_cel->h);
  407. break;
  408. case 3:
  409. scalew = XMAX;
  410. scaleh = YMAX;
  411. break;
  412. case 4:
  413. r1 = (long)XMAX*pic_cel->h;
  414. r2 = (long)YMAX*pic_cel->w;
  415. if (r1 > r2) /* need to shrink y */
  416. {
  417. scalew = pic_cel->w;
  418. scaleh = (long)(pic_cel->h * r2 / r1);
  419. }
  420. else /* need to shrink x */
  421. {
  422. scalew = (long)(pic_cel->w * r1 / r2);
  423. scaleh = pic_cel->h;
  424. }
  425. break;
  426. case 5:
  427. scalew = pic_cel->w;
  428. scaleh = pic_cel->h;
  429. break;
  430. case 6:
  431. dither = !dither;
  432. break;
  433. case 7:
  434. do_scale();
  435. break;
  436. }
  437. if (scalew <= 0)
  438. scalew = 1;
  439. if (scaleh <= 0)
  440. scaleh = 1;
  441. }
  442. }
  443. do_scale()
  444. {
  445. long l;
  446. extern unsigned mem_free;
  447. /* make sure will have enough memory before go spend 1/2 hour doing it... */
  448. l = scalew;
  449. l *= scaleh;
  450. l += 1000;
  451. if (pic_cel)
  452. l -= (long)pic_cel->w * pic_cel->h;
  453. if (l >= mem_free*16L)
  454. {
  455. outta_memory();
  456. return;
  457. }
  458. switch (intype)
  459. {
  460. case MAC:
  461. scale_mac(scalew,scaleh);
  462. break;
  463. case PCX:
  464. scale_pcx(scalew,scaleh);
  465. break;
  466. case TARGA:
  467. scale_vision(scalew,scaleh);
  468. kill_rgb_files();
  469. break;
  470. default:
  471. scale_pic_cel(scalew, scaleh);
  472. break;
  473. }
  474. }