PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/branches/bottie/src/util/rle-pix.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 363 lines | 247 code | 45 blank | 71 comment | 70 complexity | a11b60d12b53ce636be4d67792e8ca0a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* R L E - P I X . C
  2. * BRL-CAD
  3. *
  4. * Copyright (c) 2004-2011 United States Government as represented by
  5. * the U.S. Army Research Laboratory.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this file; see the file named COPYING for more
  18. * information.
  19. */
  20. /** @file rle-pix.c
  21. *
  22. * Decode a Utah Raster Toolkit RLE image, and output as a pix(5)
  23. * file.
  24. *
  25. */
  26. #include "common.h"
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "bio.h"
  30. #include "fb.h"
  31. #include "bu.h"
  32. /*
  33. * system installed RLE reports a re-define, so undef it to quell the
  34. * warning
  35. */
  36. #include "rle.h"
  37. static FILE *infp;
  38. static char *infile;
  39. static FILE *outfp;
  40. static int background[3];
  41. static int override_background;
  42. unsigned char *rows[4]; /* Character pointers for rle_getrow */
  43. static RGBpixel *scan_buf; /* single scanline buffer */
  44. static RGBpixel *bg_buf; /* single scanline of background */
  45. static ColorMap cmap;
  46. static int screen_width = 0;
  47. static int screen_height = 0;
  48. static int crunch;
  49. static int r_debug;
  50. static int hflag; /* print header only */
  51. static char usage[] = "\
  52. Usage: rle-pix [-c -d -h -H] [-C r/g/b]\n\
  53. [-s|S squareoutsize] [-w|W out_width] [-n|N out_height]\n\
  54. [file.rle [file.pix]]\n\
  55. ";
  56. /*
  57. * G E T _ A R G S
  58. */
  59. static int
  60. get_args(int argc, char **argv)
  61. {
  62. int c;
  63. while ((c = bu_getopt(argc, argv, "cdhHs:S:w:W:n:N:C:")) != EOF) {
  64. switch (c) {
  65. case 'd':
  66. r_debug = 1;
  67. break;
  68. case 'c':
  69. crunch = 1;
  70. break;
  71. case 'H':
  72. hflag = 1;
  73. break;
  74. case 'h':
  75. /* high-res */
  76. screen_height = screen_width = 1024;
  77. break;
  78. case 'S':
  79. case 's':
  80. /* square screen size */
  81. screen_height = screen_width = atoi(bu_optarg);
  82. break;
  83. case 'W':
  84. case 'w':
  85. screen_width = atoi(bu_optarg);
  86. break;
  87. case 'N':
  88. case 'n':
  89. screen_height = atoi(bu_optarg);
  90. break;
  91. case 'C':
  92. {
  93. char *cp = bu_optarg;
  94. int *conp = background;
  95. /* premature null => atoi gives zeros */
  96. for (c=0; c < 3; c++) {
  97. *conp++ = atoi(cp);
  98. while (*cp && *cp++ != '/')
  99. ;
  100. }
  101. override_background = 1;
  102. }
  103. break;
  104. default:
  105. case '?':
  106. return 0;
  107. }
  108. }
  109. if (argv[bu_optind] != NULL) {
  110. if ((infp = fopen((infile=argv[bu_optind]), "r")) == NULL) {
  111. perror(infile);
  112. return 0;
  113. }
  114. bu_optind++;
  115. } else {
  116. infile = "-";
  117. }
  118. if (argv[bu_optind] != NULL) {
  119. if (bu_file_exists(argv[bu_optind])) {
  120. bu_exit(1, "rle-pix: \"%s\" already exists.\n", argv[bu_optind]);
  121. }
  122. if ((outfp = fopen(argv[bu_optind], "w")) == NULL) {
  123. perror(argv[bu_optind]);
  124. return 0;
  125. }
  126. }
  127. if (argc > ++bu_optind)
  128. bu_log("rle-pix: excess arguments ignored\n");
  129. if (isatty(fileno(infp)))
  130. return 0;
  131. if (!hflag && isatty(fileno(outfp)))
  132. return 0;
  133. return 1; /* OK */
  134. }
  135. /*
  136. * M A I N
  137. */
  138. int
  139. main(int argc, char **argv)
  140. {
  141. int i;
  142. int file_width; /* unclipped width of rectangle */
  143. int file_skiplen; /* # of pixels to skip on l.h.s. */
  144. int screen_xbase; /* screen X of l.h.s. of rectangle */
  145. int screen_xlen; /* clipped len of rectangle */
  146. int ncolors;
  147. size_t ret;
  148. infp = stdin;
  149. outfp = stdout;
  150. if (!get_args(argc, argv)) {
  151. bu_exit(1, "%s", usage);
  152. }
  153. rle_dflt_hdr.rle_file = infp;
  154. if (rle_get_setup(&rle_dflt_hdr) < 0) {
  155. bu_exit(1, "rle-pix: Error reading setup information\n");
  156. }
  157. if (r_debug) {
  158. bu_log("Image bounds\n\tmin %d %d\n\tmax %d %d\n",
  159. rle_dflt_hdr.xmin, rle_dflt_hdr.ymin,
  160. rle_dflt_hdr.xmax, rle_dflt_hdr.ymax);
  161. bu_log("%d color channels\n", rle_dflt_hdr.ncolors);
  162. bu_log("%d color map channels\n", rle_dflt_hdr.ncmap);
  163. if (rle_dflt_hdr.alpha)
  164. bu_log("Alpha Channel present in input, ignored.\n");
  165. for (i=0; i < rle_dflt_hdr.ncolors; i++)
  166. bu_log("Background channel %d = %d\n",
  167. i, rle_dflt_hdr.bg_color[i]);
  168. rle_debug(1);
  169. }
  170. if (rle_dflt_hdr.ncmap == 0)
  171. crunch = 0;
  172. /* Only interested in R, G, & B */
  173. RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA);
  174. for (i = 3; i < rle_dflt_hdr.ncolors; i++)
  175. RLE_CLR_BIT(rle_dflt_hdr, i);
  176. ncolors = rle_dflt_hdr.ncolors > 3 ? 3 : rle_dflt_hdr.ncolors;
  177. /* Optional background color override */
  178. if (override_background) {
  179. for (i=0; i<ncolors; i++)
  180. rle_dflt_hdr.bg_color[i] = background[i];
  181. }
  182. file_width = rle_dflt_hdr.xmax - rle_dflt_hdr.xmin + 1;
  183. /* Default screen (output) size tracks input rectangle upper right corner */
  184. if (screen_width == 0) {
  185. screen_width = rle_dflt_hdr.xmax + 1;
  186. }
  187. if (screen_height == 0) {
  188. screen_height = rle_dflt_hdr.ymax + 1;
  189. }
  190. /* Report screen (output) size given image size & other options */
  191. if (hflag) {
  192. printf("-w%d -n%d\n",
  193. screen_width, screen_height);
  194. return 0;
  195. }
  196. /* Discard any scanlines which exceed screen height */
  197. if (rle_dflt_hdr.ymax > screen_height-1)
  198. rle_dflt_hdr.ymax = screen_height-1;
  199. /* Clip left edge */
  200. screen_xbase = rle_dflt_hdr.xmin;
  201. screen_xlen = screen_width;
  202. file_skiplen = 0;
  203. if (screen_xbase < 0) {
  204. file_skiplen = -screen_xbase;
  205. screen_xbase = 0;
  206. screen_xlen -= file_skiplen;
  207. }
  208. /* Clip right edge */
  209. if (screen_xbase + screen_xlen > screen_width)
  210. screen_xlen = screen_width - screen_xbase;
  211. if (screen_xlen <= 0 || rle_dflt_hdr.ymin > screen_height || rle_dflt_hdr.ymax < 0) {
  212. bu_log("rle-pix: Warning: RLE image rectangle entirely off screen\n");
  213. goto done;
  214. }
  215. /* NOTE: This code can't do repositioning very well.
  216. * background flooding on the edges is needed, at a minimum.
  217. */
  218. scan_buf = (RGBpixel *)bu_malloc(sizeof(RGBpixel) * screen_width, "scan_buf");
  219. bg_buf = (RGBpixel *)bu_malloc(sizeof(RGBpixel) * screen_width, "bg_buf");
  220. /* Fill in background buffer */
  221. if (!rle_dflt_hdr.bg_color) {
  222. (void)memset((char *)bg_buf, 0, sizeof(RGBpixel) * screen_width);
  223. } else {
  224. for (i=0; i<screen_xlen; i++) {
  225. bg_buf[i][0] = rle_dflt_hdr.bg_color[0];
  226. bg_buf[i][1] = rle_dflt_hdr.bg_color[1];
  227. bg_buf[i][2] = rle_dflt_hdr.bg_color[2];
  228. }
  229. }
  230. for (i=0; i < ncolors; i++)
  231. rows[i] = (unsigned char *)bu_malloc((size_t)file_width, "row[]");
  232. for (; i < 3; i++)
  233. rows[i] = rows[0]; /* handle monochrome images */
  234. /*
  235. * Import Utah color map, converting to libfb format.
  236. * Check for old format color maps, where high 8 bits
  237. * were zero, and correct them.
  238. * XXX need to handle < 3 channels of color map, by replication.
  239. */
  240. if (crunch && rle_dflt_hdr.ncmap > 0) {
  241. int maplen = (1 << rle_dflt_hdr.cmaplen);
  242. int all = 0;
  243. for (i=0; i<256; i++) {
  244. cmap.cm_red[i] = rle_dflt_hdr.cmap[i];
  245. cmap.cm_green[i] = rle_dflt_hdr.cmap[i+maplen];
  246. cmap.cm_blue[i] = rle_dflt_hdr.cmap[i+2*maplen];
  247. all |= cmap.cm_red[i] | cmap.cm_green[i] |
  248. cmap.cm_blue[i];
  249. }
  250. if ((all & 0xFF00) == 0 && (all & 0x00FF) != 0) {
  251. /* This is an old (Edition 2) color map.
  252. * Correct by shifting it left 8 bits.
  253. */
  254. for (i=0; i<256; i++) {
  255. cmap.cm_red[i] <<= 8;
  256. cmap.cm_green[i] <<= 8;
  257. cmap.cm_blue[i] <<= 8;
  258. }
  259. bu_log("rle-pix: correcting for old style colormap\n");
  260. }
  261. }
  262. /* Handle any lines below zero in y. Decode and discard. */
  263. for (i = rle_dflt_hdr.ymin; i < 0; i++)
  264. rle_getrow(&rle_dflt_hdr, rows);
  265. /* Background-fill any lines above 0, below ymin */
  266. for (i=0; i < rle_dflt_hdr.ymin; i++) {
  267. ret = fwrite((char *)bg_buf, sizeof(RGBpixel), (size_t)screen_xlen, outfp);
  268. if (ret == 0)
  269. perror("fwrite");
  270. }
  271. for (; i <= rle_dflt_hdr.ymax; i++) {
  272. unsigned char *pp = (unsigned char *)scan_buf;
  273. rle_pixel *rp = &(rows[0][file_skiplen]);
  274. rle_pixel *gp = &(rows[1][file_skiplen]);
  275. rle_pixel *bp = &(rows[2][file_skiplen]);
  276. int j;
  277. rle_getrow(&rle_dflt_hdr, rows);
  278. /* Grumble, convert from Utah layout */
  279. if (!crunch) {
  280. for (j = 0; j < screen_xlen; j++) {
  281. *pp++ = *rp++;
  282. *pp++ = *gp++;
  283. *pp++ = *bp++;
  284. }
  285. } else {
  286. for (j = 0; j < screen_xlen; j++) {
  287. *pp++ = cmap.cm_red[*rp++]>>8;
  288. *pp++ = cmap.cm_green[*gp++]>>8;
  289. *pp++ = cmap.cm_blue[*bp++]>>8;
  290. }
  291. }
  292. ret = fwrite((char *)scan_buf, sizeof(RGBpixel), (size_t)screen_xlen, outfp);
  293. if (ret == 0)
  294. perror("fwrite");
  295. }
  296. /* Background-fill any lines above ymax, below screen_height */
  297. for (; i < screen_height; i++) {
  298. ret = fwrite((char *)bg_buf, sizeof(RGBpixel), (size_t)screen_xlen, outfp);
  299. if (ret == 0)
  300. perror("fwrite");
  301. }
  302. done:
  303. for (i=0; i < ncolors; i++)
  304. bu_free(rows[i], "row[]");
  305. bu_free(scan_buf, "scan_buf");
  306. bu_free(bg_buf, "bg_buf");
  307. fclose(outfp);
  308. return 0;
  309. }
  310. /*
  311. * Local Variables:
  312. * mode: C
  313. * tab-width: 8
  314. * indent-tabs-mode: t
  315. * c-file-style: "stroustrup"
  316. * End:
  317. * ex: shiftwidth=4 tabstop=8
  318. */