/bundler-v0.4-source-sba-1.6/lib/imagelib/binvolume.c

https://bitbucket.org/ecosynth/ecosynther · C · 351 lines · 255 code · 61 blank · 35 comment · 81 complexity · 9f5e44466fb53fb4b2bf71f5a72a09cb MD5 · raw file

  1. /*
  2. * Copyright (c) 2008 Noah Snavely (snavely (at) cs.washington.edu)
  3. * and the University of Washington
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <math.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "binvolume.h"
  21. #include "bmp.h"
  22. #include "defines.h"
  23. #include "image.h"
  24. #include "pad.h"
  25. #define BIN_VOLUME_HEADER "BVOL"
  26. // #define NUMBITS(b) (BIT_PAD_WORD((b)->w) * BIT_PAD_WORD((b)->h) * BIT_PAD_WORD((b)->d))
  27. #define NUMBITS(b) (BIT_PAD_WORD((b)->d * BIT_PAD_WORD((b)->h * BIT_PAD_WORD((b)->w))))
  28. #define NUMBYTES(b) ((NUMBITS(b) >> 3) + ((NUMBITS(b) % 8 == 0) ? 0 : 1))
  29. #define BVOL_PLANE_BYTES(b) (BIT_PAD_WORD((b)->h * BIT_PAD_WORD((b)->w)) / 8)
  30. /* Turn on a bit in the volume */
  31. void bvol_setbit(bvol_t *b, int x, int y, int z) {
  32. if (x < 0 || y < 0 || z < 0 || x >= (int) b->w || y >= (int) b->h || z >= (int) b->d) {
  33. return;
  34. } else {
  35. if (b->type == BVOL_BITS) {
  36. int bit_num = z * BIT_PAD_WORD(b->h * BIT_PAD_WORD(b->w)) +
  37. y * BIT_PAD_WORD(b->w) + x;
  38. int byte_num = (bit_num >> 3);
  39. int bit_idx = 7 - (bit_num % 8);
  40. b->data.bits[byte_num] |= (1 << bit_idx);
  41. } else {
  42. b->data.heights[y * b->w + x] = z;
  43. }
  44. }
  45. }
  46. /* Get the value of a bit in the volume */
  47. u_int8_t bvol_getbit(bvol_t *b, int x, int y, int z) {
  48. if (x < 0 || y < 0 || z < 0 || x >= (int) b->w || y >= (int) b->h || z >= (int) b->d) {
  49. return 0;
  50. } else {
  51. if (b->type == BVOL_BITS) {
  52. int bit_num = z * BIT_PAD_WORD(b->h * BIT_PAD_WORD(b->w)) +
  53. y * BIT_PAD_WORD(b->w) + x;
  54. int byte_num = (bit_num >> 3);
  55. int bit_idx = 7 - (bit_num % 8);
  56. return (b->data.bits[byte_num] & (1 << bit_idx)) ? 1 : 0;
  57. } else {
  58. return (b->data.heights[y * b->w + x] == z) ? 1 : 0;
  59. }
  60. }
  61. }
  62. /* Returns the number of bits set in the binary volume */
  63. u_int32_t bvol_num_points(bvol_t *b) {
  64. if (b->type == BVOL_BITS) {
  65. int x, y, z;
  66. u_int32_t num_bits = 0;
  67. for (z = 0; z < (int) b->d; z++)
  68. for (y = 0; y < (int) b->h; y++)
  69. for (x = 0; x < (int) b->w; x++)
  70. if (bvol_getbit(b, x, y, z))
  71. num_bits++;
  72. return num_bits;
  73. } else {
  74. return b->w * b->h;
  75. }
  76. }
  77. /* Create and return an empty binary volume */
  78. bvol_t *new_bin_volume(int w, int h, int d, bvol_type_t type) {
  79. bvol_t *b = malloc(sizeof(bvol_t));
  80. b->w = w; b->h = h; b->d = d;
  81. b->type = type;
  82. if (type == BVOL_BITS)
  83. b->data.bits = calloc(NUMBYTES(b), 1);
  84. else {
  85. if (d != 256)
  86. printf("Error: binary volume with heights should have depth 256\n");
  87. d = 256;
  88. b->data.heights = calloc(b->w * b->h, 1);
  89. }
  90. return b;
  91. }
  92. /* Create a copy of a binary volume */
  93. bvol_t *bvol_copy(bvol_t *b) {
  94. bvol_t *bnew = new_bin_volume(b->w, b->h, b->d, b->type);
  95. if (bnew->type == BVOL_BITS)
  96. memcpy(bnew->data.bits, b->data.bits, NUMBYTES(bnew));
  97. else
  98. memcpy(bnew->data.heights, b->data.heights, bnew->w * bnew->h);
  99. return bnew;
  100. }
  101. double bvol_gradient(bvol_t *b, int x, int y, int z) {
  102. double dx, dy;
  103. double max_grad = 2 * b->d * b->d;
  104. if (x == 0)
  105. dx = BVOL_HEIGHT(b, x + 1, y) - BVOL_HEIGHT(b, x, y);
  106. else if (x == b->w - 1)
  107. dx = BVOL_HEIGHT(b, x, y) - BVOL_HEIGHT(b, x - 1, y);
  108. else
  109. dx = BVOL_HEIGHT(b, x + 1, y) - BVOL_HEIGHT(b, x - 1, y);
  110. if (y == 0)
  111. dy = BVOL_HEIGHT(b, x, y + 1) - BVOL_HEIGHT(b, x, y);
  112. else if (y == b->h - 1)
  113. dy = BVOL_HEIGHT(b, x, y) - BVOL_HEIGHT(b, x, y - 1);
  114. else
  115. dy = BVOL_HEIGHT(b, x, y + 1) - BVOL_HEIGHT(b, x, y - 1);
  116. return sqrt(dx * dx + dy * dy) / max_grad;
  117. }
  118. bvol_t *bmp2bvm(bmp_t *bmp) {
  119. int w = BMP_WIDTH(bmp), h = BMP_HEIGHT(bmp), d = 256;
  120. int x, y;
  121. bvol_t *b = new_bin_volume(w, h, d, BVOL_HEIGHTS);
  122. for (y = 0; y < h; y++) {
  123. for (x = 0; x < w; x++) {
  124. bvol_setbit(b, x, y, BMP_GET_PIXEL(bmp, x, y));
  125. }
  126. }
  127. return b;
  128. }
  129. bvol_t *img2bvm(img_t *img) {
  130. bvol_t *bvol = new_bin_volume(img->w, img->h, 256, BVOL_HEIGHTS);
  131. int x, y;
  132. for (y = 0; y < img->h; y++) {
  133. for (x = 0; x < img->w; x++) {
  134. int z = img->pixels[y * img->w + x].r;
  135. bvol_setbit(bvol, x, y, z);
  136. }
  137. }
  138. return bvol;
  139. }
  140. img_t *bvm2img(bvol_t *b) {
  141. img_t *img = NULL;
  142. int x, y, z;
  143. int set;
  144. if (b->d != 256) {
  145. printf("Cannot create image\n");
  146. return NULL;
  147. }
  148. img = img_new(b->w, b->h);
  149. for (y = 0; y < (int) b->h; y++) {
  150. for (x = 0; x < (int) b->w; x++) {
  151. set = 0;
  152. for (z = 0; z < (int) b->d; z++) {
  153. if (bvol_getbit(b, x, y, z)) {
  154. img_set_pixel(img, x, y, z, z, z);
  155. set = 1;
  156. }
  157. }
  158. if (!set) {
  159. img_set_pixel(img, x, y, 0, 0, 0);
  160. }
  161. }
  162. }
  163. return img;
  164. }
  165. bmp_t *bvm2bmp(bvol_t *b) {
  166. bmp_t *bmp = malloc(sizeof(bmp_t));
  167. bmp_file_header_t file_header;
  168. bmp_info_header_t info_header;
  169. int x, y, z = 0;
  170. int data_bytes;
  171. int set;
  172. if (b->d != 256) {
  173. printf("Cannot create bitmap\n");
  174. free(bmp);
  175. return NULL;
  176. }
  177. data_bytes = BYTE_PAD_WORD(3 * b->w) * b->h;
  178. /* Fill the file header */
  179. file_header.filesize = 14 + sizeof(bmp_info_header_t) + data_bytes;
  180. file_header.offset = 14 + sizeof(bmp_info_header_t);
  181. /* Fill the info header */
  182. info_header.header_size = sizeof(bmp_info_header_t);
  183. info_header.width = b->w;
  184. info_header.height = b->h;
  185. info_header.num_planes = 1;
  186. info_header.bits_per_pixel = 24;
  187. info_header.compression_type = 0;
  188. info_header.image_size = data_bytes;
  189. info_header.x_pixels_per_meter = 2834;
  190. info_header.y_pixels_per_meter = 2834;
  191. info_header.colors_used = 0x0;
  192. info_header.colors_important = 0x0;
  193. /* Fill the bitmap struct */
  194. bmp->file_header = file_header;
  195. bmp->info_header = info_header;
  196. /* Fill in the pixel data */
  197. bmp->pixels = malloc(sizeof(color_t) * b->w * b->h);
  198. for (y = 0; y < (int) b->h; y++) {
  199. for (x = 0; x < (int) b->w; x++) {
  200. set = 0;
  201. for (z = 0; z < (int) b->d; z++) {
  202. if (bvol_getbit(b, x, y, z)) {
  203. bmp->pixels[y * b->w + x].r = z;
  204. bmp->pixels[y * b->w + x].g = z;
  205. bmp->pixels[y * b->w + x].b = z;
  206. set = 1;
  207. }
  208. }
  209. if (!set) {
  210. bmp->pixels[y * b->w + x].r = 0xff;
  211. bmp->pixels[y * b->w + x].g = 0xff;
  212. bmp->pixels[y * b->w + x].b = 0xff;
  213. }
  214. }
  215. }
  216. return bmp;
  217. }
  218. void write_bin_volume(FILE *f, bvol_t *b) {
  219. u_int32_t type;
  220. /* Write the header */
  221. fwrite(BIN_VOLUME_HEADER, 4, 1, f);
  222. /* Write the width, height, depth */
  223. fwrite(&b->w, 4, 1, f);
  224. fwrite(&b->h, 4, 1, f);
  225. fwrite(&b->d, 4, 1, f);
  226. /* Write the type */
  227. type = b->type;
  228. fwrite(&type, 4, 1, f);
  229. /* Write the data */
  230. if (type == BVOL_BITS) {
  231. int bytes = NUMBYTES(b);
  232. fwrite(b->data.bits, 1, bytes, f);
  233. } else {
  234. fwrite(b->data.heights, 1, b->w * b->h, f);
  235. }
  236. }
  237. bvol_t *read_bin_volume(FILE *f) {
  238. bvol_t *b = NULL;
  239. char hdr[5] = "";
  240. u_int32_t w, h, d, type, bytes;
  241. /* Read the header */
  242. fread(hdr, 1, 4, f);
  243. hdr[4] = 0;
  244. if (strcmp(hdr, BIN_VOLUME_HEADER) != 0) {
  245. printf("Error: file is not a valid binary volume\n");
  246. fclose(f);
  247. return NULL;
  248. }
  249. /* Read the width, height, and depth */
  250. fread(&w, 4, 1, f);
  251. fread(&h, 4, 1, f);
  252. fread(&d, 4, 1, f);
  253. /* Read the type */
  254. fread(&type, 4, 1, f);
  255. b = new_bin_volume(w, h, d, type);
  256. /* Read in the data */
  257. if (type == BVOL_BITS) {
  258. bytes = NUMBYTES(b);
  259. fread(b->data.bits, 1, bytes, f);
  260. } else {
  261. fread(b->data.heights, 1, w * h, f);
  262. }
  263. return b;
  264. }
  265. /* Slice a plane out of the given binary volume, storing the result in
  266. * bimg */
  267. bimg_t *slice_bin_volume(bvol_t *bvol, int z) {
  268. bimg_t *bimg = new_bin_image(bvol->w, bvol->h);
  269. if (bvol->type == BVOL_BITS) {
  270. memcpy(bimg->bits,
  271. bvol->data.bits + z * BVOL_PLANE_BYTES(bvol),
  272. BVOL_PLANE_BYTES(bvol));
  273. } else {
  274. int x, y;
  275. for (y = 0; y < (int) bvol->h; y++) {
  276. for (x = 0; x < (int) bvol->w; x++) {
  277. if (bvol_getbit(bvol, x, y, z))
  278. bimg_setbit(bimg, x, y);
  279. }
  280. }
  281. }
  282. return bimg;
  283. }
  284. void free_bin_volume(bvol_t *b) {
  285. if (b->type == BVOL_BITS)
  286. free(b->data.bits);
  287. else
  288. free(b->data.heights);
  289. free(b);
  290. }