i_rle.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* This file (i_rle.c) is a module that does run-length encoding on
  16. a sequence of integers ("pixel values"), and writes the resulting
  17. encoded sequence to an output stream. The accompanying header file
  18. (i_rle.h) defines the external interface. The encoded sequence
  19. should be GIF-compatible, even though the compression technique
  20. is not LZW.
  21. This module encapsulates the miGIF compression routines, originally
  22. written by der Mouse and ivo. Their copyright notice is reproduced
  23. below. */
  24. /*-----------------------------------------------------------------------
  25. *
  26. * miGIF Compression - mouse and ivo's GIF-compatible compression
  27. *
  28. * -run length encoding compression routines-
  29. *
  30. * Copyright (C) 1998 Hutchison Avenue Software Corporation
  31. * http://www.hasc.com
  32. * info@hasc.com
  33. *
  34. * Permission to use, copy, modify, and distribute this software and its
  35. * documentation for any purpose and without fee is hereby granted, provided
  36. * that the above copyright notice appear in all copies and that both that
  37. * copyright notice and this permission notice appear in supporting
  38. * documentation. This software is provided "AS IS." The Hutchison Avenue
  39. * Software Corporation disclaims all warranties, either express or implied,
  40. * including but not limited to implied warranties of merchantability and
  41. * fitness for a particular purpose, with respect to this code and accompanying
  42. * documentation.
  43. *
  44. * The miGIF compression routines do not, strictly speaking, generate files
  45. * conforming to the GIF spec, since the image data is not LZW-compressed
  46. * (this is the point: in order to avoid transgression of the Unisys patent
  47. * on the LZW algorithm.) However, miGIF generates data streams that any
  48. * reasonably sane LZW decompresser will decompress to what we want.
  49. *
  50. * miGIF compression uses run length encoding. It compresses horizontal runs
  51. * of pixels of the same color. This type of compression gives good results
  52. * on images with many runs, for example images with lines, text and solid
  53. * shapes on a solid-colored background. It gives little or no compression
  54. * on images with few runs, for example digital or scanned photos.
  55. *
  56. * der Mouse
  57. * mouse@rodents.montreal.qc.ca
  58. * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
  59. *
  60. * ivo@hasc.com
  61. *
  62. * The Graphics Interchange Format(c) is the Copyright property of
  63. * CompuServe Incorporated. GIF(sm) is a Service Mark property of
  64. * CompuServe Incorporated.
  65. *
  66. */
  67. #include "sys-defines.h" /* libplot-specific */
  68. #include "extern.h" /* libplot-specific */
  69. #include "i_rle.h"
  70. /* forward references */
  71. static void _block_out (rle_out *rle, unsigned char c);
  72. static void
  73. _write_block (rle_out *rle)
  74. {
  75. if (rle->ofile)
  76. {
  77. fputc (rle->oblen, rle->ofile);
  78. fwrite ((void *) &(rle->oblock[0]), 1, rle->oblen, rle->ofile);
  79. }
  80. #ifdef LIBPLOTTER
  81. else if (rle->outstream)
  82. {
  83. rle->outstream->put ((unsigned char)(rle->oblen));
  84. rle->outstream->write ((const char *)(&(rle->oblock[0])), rle->oblen);
  85. }
  86. #endif
  87. rle->oblen = 0;
  88. }
  89. static void
  90. _block_out (rle_out *rle, unsigned char c)
  91. {
  92. rle->oblock[(rle->oblen)++] = c;
  93. if (rle->oblen >= 255)
  94. _write_block (rle);
  95. }
  96. static void
  97. _block_flush (rle_out *rle)
  98. {
  99. if (rle->oblen > 0)
  100. _write_block (rle);
  101. }
  102. static void
  103. _output (rle_out *rle, int val)
  104. {
  105. rle->obuf |= val << rle->obits;
  106. rle->obits += rle->out_bits;
  107. while (rle->obits >= 8)
  108. {
  109. _block_out (rle, (unsigned char)(rle->obuf & 0xff));
  110. rle->obuf >>= 8;
  111. rle->obits -= 8;
  112. }
  113. }
  114. static void
  115. _output_flush (rle_out *rle)
  116. {
  117. if (rle->obits > 0)
  118. _block_out (rle, (unsigned char)(rle->obuf));
  119. _block_flush (rle);
  120. }
  121. static void
  122. _did_clear (rle_out *rle)
  123. {
  124. rle->out_bits = rle->out_bits_init;
  125. rle->out_bump = rle->out_bump_init;
  126. rle->out_clear = rle->out_clear_init;
  127. rle->out_count = 0;
  128. rle->rl_table_max = 0;
  129. rle->just_cleared = true;
  130. }
  131. static void
  132. _output_plain (rle_out *rle, int c)
  133. {
  134. rle->just_cleared = false;
  135. _output (rle, c);
  136. rle->out_count++;
  137. if (rle->out_count >= rle->out_bump)
  138. {
  139. rle->out_bits++;
  140. rle->out_bump += 1 << (rle->out_bits - 1);
  141. }
  142. if (rle->out_count >= rle->out_clear)
  143. {
  144. _output (rle, rle->code_clear);
  145. _did_clear (rle);
  146. }
  147. }
  148. static unsigned int
  149. _isqrt (unsigned int x)
  150. {
  151. unsigned int r;
  152. unsigned int v;
  153. if (x < 2)
  154. return x;
  155. for (v=x, r=1; v; v>>=2, r<<=1)
  156. ;
  157. for ( ; ; )
  158. {
  159. v = ((x / r) + r) / 2;
  160. if ((v == r) || (v == r+1))
  161. return r;
  162. r = v;
  163. }
  164. }
  165. static unsigned int
  166. _compute_triangle_count (unsigned int count, unsigned int nrepcodes)
  167. {
  168. unsigned int perrep, cost;
  169. cost = 0;
  170. perrep = (nrepcodes * (nrepcodes+1)) / 2;
  171. while (count >= perrep)
  172. {
  173. cost += nrepcodes;
  174. count -= perrep;
  175. }
  176. if (count > 0)
  177. {
  178. unsigned int n;
  179. n = _isqrt (count);
  180. while ((n*(n+1)) >= 2*count)
  181. n--;
  182. while ((n*(n+1)) < 2*count)
  183. n++;
  184. cost += n;
  185. }
  186. return cost;
  187. }
  188. static void
  189. _max_out_clear (rle_out *rle)
  190. {
  191. rle->out_clear = rle->max_ocodes;
  192. }
  193. static void
  194. _reset_out_clear (rle_out *rle)
  195. {
  196. rle->out_clear = rle->out_clear_init;
  197. if (rle->out_count >= rle->out_clear)
  198. {
  199. _output (rle, rle->code_clear);
  200. _did_clear (rle);
  201. }
  202. }
  203. static void
  204. _rl_flush_fromclear (rle_out *rle, int count)
  205. {
  206. int n;
  207. _max_out_clear (rle);
  208. rle->rl_table_pixel = rle->rl_pixel;
  209. n = 1;
  210. while (count > 0)
  211. {
  212. if (n == 1)
  213. {
  214. rle->rl_table_max = 1;
  215. _output_plain (rle, rle->rl_pixel);
  216. count--;
  217. }
  218. else if (count >= n)
  219. {
  220. rle->rl_table_max = n;
  221. _output_plain (rle, rle->rl_basecode + n - 2);
  222. count -= n;
  223. }
  224. else if (count == 1)
  225. {
  226. (rle->rl_table_max)++;
  227. _output_plain (rle, rle->rl_pixel);
  228. count = 0;
  229. }
  230. else
  231. {
  232. rle->rl_table_max++;
  233. _output_plain (rle, rle->rl_basecode+count-2);
  234. count = 0;
  235. }
  236. if (rle->out_count == 0)
  237. n = 1;
  238. else
  239. n++;
  240. }
  241. _reset_out_clear (rle);
  242. }
  243. static void
  244. _rl_flush_clearorrep (rle_out *rle, int count)
  245. {
  246. int withclr;
  247. withclr = 1 + _compute_triangle_count ((unsigned int)count,
  248. (unsigned int)(rle->max_ocodes));
  249. if (withclr < count)
  250. {
  251. _output (rle, rle->code_clear);
  252. _did_clear (rle);
  253. _rl_flush_fromclear (rle, count);
  254. }
  255. else
  256. for ( ; count>0; count--)
  257. _output_plain (rle, rle->rl_pixel);
  258. }
  259. static void
  260. _rl_flush_withtable (rle_out *rle, int count)
  261. {
  262. int repmax;
  263. int repleft;
  264. int leftover;
  265. repmax = count / rle->rl_table_max;
  266. leftover = count % rle->rl_table_max;
  267. repleft = (leftover ? 1 : 0);
  268. if (rle->out_count + repmax + repleft > rle->max_ocodes)
  269. {
  270. repmax = rle->max_ocodes - rle->out_count;
  271. leftover = count - (repmax * rle->rl_table_max);
  272. repleft = 1 + _compute_triangle_count ((unsigned int)leftover,
  273. (unsigned int)(rle->max_ocodes));
  274. }
  275. if (1 + _compute_triangle_count ((unsigned int)count,
  276. (unsigned int)(rle->max_ocodes))
  277. < repmax + repleft)
  278. {
  279. _output (rle, rle->code_clear);
  280. _did_clear (rle);
  281. _rl_flush_fromclear (rle, count);
  282. return;
  283. }
  284. _max_out_clear (rle);
  285. for ( ; repmax>0; repmax--)
  286. _output_plain (rle, rle->rl_basecode + rle->rl_table_max - 2);
  287. if (leftover)
  288. {
  289. if (rle->just_cleared)
  290. _rl_flush_fromclear (rle, leftover);
  291. else if (leftover == 1)
  292. _output_plain (rle, rle->rl_pixel);
  293. else
  294. _output_plain (rle, rle->rl_basecode + leftover - 2);
  295. }
  296. _reset_out_clear (rle);
  297. }
  298. /* end a run in progress */
  299. static void
  300. _rl_flush (rle_out *rle)
  301. {
  302. if (rle->rl_count == 1) /* not a real run, just output pixel */
  303. _output_plain (rle, rle->rl_pixel);
  304. else
  305. {
  306. if (rle->just_cleared)
  307. _rl_flush_fromclear (rle, rle->rl_count);
  308. else if ((rle->rl_table_max < 2)
  309. || (rle->rl_table_pixel != rle->rl_pixel))
  310. _rl_flush_clearorrep (rle, rle->rl_count);
  311. else
  312. _rl_flush_withtable (rle, rle->rl_count);
  313. }
  314. rle->rl_count = 0;
  315. }
  316. /***********************************************************************/
  317. /* EXTERNAL INTERFACE */
  318. /***********************************************************************/
  319. /* create new RLE struct, which writes to a specified stream */
  320. rle_out *
  321. #ifdef LIBPLOTTER
  322. _rle_init (FILE *fp, ostream *out, int bit_depth)
  323. #else
  324. _rle_init (FILE *fp, int bit_depth)
  325. #endif
  326. {
  327. int init_bits;
  328. rle_out *rle;
  329. /* Initial length for compression codes, one bit longer than the minimum
  330. number of bits needed to represent the set of pixel values. The
  331. IMAX() and the addition of 1 bit are "because of some algorithmic
  332. constraints". */
  333. init_bits = IMAX(bit_depth, 2) + 1;
  334. rle = (rle_out *)_pl_xmalloc(sizeof(rle_out));
  335. rle->ofile = fp;
  336. #ifdef LIBPLOTTER
  337. rle->outstream = out;
  338. #endif
  339. rle->obuf = 0;
  340. rle->obits = 0;
  341. rle->oblen = 0;
  342. rle->code_clear = 1 << (init_bits - 1); /* 100..000 */
  343. rle->code_eof = rle->code_clear + 1; /* 100..001 */
  344. rle->rl_basecode = rle->code_eof + 1; /* 100..010 */
  345. rle->out_bump_init = (1 << (init_bits - 1)) - 1; /* 011..111 */
  346. /* for images with a lot of runs, making out_clear_init larger will
  347. give better compression. */
  348. /* 011..110 */
  349. rle->out_clear_init = (init_bits <= 3) ? 9 : (rle->out_bump_init - 1);
  350. rle->out_bits_init = init_bits;
  351. rle->max_ocodes = (1 << GIFBITS) - ((1 << (rle->out_bits_init - 1)) + 3);
  352. _did_clear (rle);
  353. _output (rle, rle->code_clear);
  354. rle->rl_count = 0;
  355. return rle;
  356. }
  357. /* send one pixel to the RLE */
  358. void
  359. _rle_do_pixel (rle_out *rle, int c)
  360. {
  361. /* if a run needs to be terminated by being written out, do so */
  362. if ((rle->rl_count > 0) && (c != rle->rl_pixel))
  363. _rl_flush (rle);
  364. /* if current run can be continued, do so (internally) */
  365. if (rle->rl_pixel == c)
  366. rle->rl_count++;
  367. /* otherwise start a new one */
  368. else
  369. {
  370. rle->rl_pixel = c;
  371. rle->rl_count = 1;
  372. }
  373. }
  374. /* flush out any data remaining in RLE; write EOF and deallocate RLE */
  375. void
  376. _rle_terminate (rle_out *rle)
  377. {
  378. /* if a run in progress, end it */
  379. if (rle->rl_count > 0)
  380. _rl_flush (rle);
  381. _output (rle, rle->code_eof);
  382. _output_flush (rle);
  383. /* deallocate */
  384. free (rle);
  385. }