readbmp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <draw.h>
  13. #include "imagefile.h"
  14. #include "bmp.h"
  15. /*
  16. MS-BMP file reader
  17. (c) 2003, I.P.Keller
  18. aims to decode *all* valid bitmap formats, although some of the
  19. flavours couldn't be verified due to lack of suitable test-files.
  20. the following flavours are supported:
  21. Bit/Pix Orientation Compression Tested?
  22. 1 top->bottom n/a yes
  23. 1 bottom->top n/a yes
  24. 4 top->bottom no yes
  25. 4 bottom->top no yes
  26. 4 top->bottom RLE4 yes, but not with displacement
  27. 8 top->bottom no yes
  28. 8 bottom->top no yes
  29. 8 top->bottom RLE8 yes, but not with displacement
  30. 16 top->bottom no no
  31. 16 bottom->top no no
  32. 16 top->bottom BITMASK no
  33. 16 bottom->top BITMASK no
  34. 24 top->bottom n/a yes
  35. 24 bottom->top n/a yes
  36. 32 top->bottom no no
  37. 32 bottom->top no no
  38. 32 top->bottom BITMASK no
  39. 32 bottom->top BITMASK no
  40. OS/2 1.x bmp files are recognised as well, but testing was very limited.
  41. verifying was done with a number of test files, generated by
  42. different tools. nevertheless, the tests were in no way exhaustive
  43. enough to guarantee bug-free decoding. caveat emptor!
  44. */
  45. static int16_t
  46. r16(Biobuf*b)
  47. {
  48. int16_t s;
  49. s = Bgetc(b);
  50. s |= ((int16_t)Bgetc(b)) << 8;
  51. return s;
  52. }
  53. static int32_t
  54. r32(Biobuf*b)
  55. {
  56. int32_t l;
  57. l = Bgetc(b);
  58. l |= ((int32_t)Bgetc(b)) << 8;
  59. l |= ((int32_t)Bgetc(b)) << 16;
  60. l |= ((int32_t)Bgetc(b)) << 24;
  61. return l;
  62. }
  63. /* get highest bit set */
  64. static int
  65. msb(uint32_t x)
  66. {
  67. int i;
  68. for(i = 32; i; i--, x <<= 1)
  69. if(x & 0x80000000L)
  70. return i;
  71. return 0;
  72. }
  73. /* Load a 1-Bit encoded BMP file (uncompressed) */
  74. static int
  75. load_1T(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  76. {
  77. int32_t ix, iy, i = 0, step_up = 0, padded_width = ((width + 31) / 32) * 32;
  78. int val = 0, n;
  79. if(height > 0) { /* bottom-up */
  80. i = (height - 1) * width;
  81. step_up = -2 * width;
  82. } else
  83. height = -height;
  84. for(iy = height; iy; iy--, i += step_up)
  85. for(ix = 0, n = 0; ix < padded_width; ix++, n--) {
  86. if(!n) {
  87. val = Bgetc(b);
  88. n = 8;
  89. }
  90. if(ix < width) {
  91. buf[i] = clut[val & 0x80 ? 1 : 0];
  92. i++;
  93. }
  94. val <<= 1;
  95. }
  96. return 0;
  97. }
  98. /* Load a 4-Bit encoded BMP file (uncompressed) */
  99. static int
  100. load_4T(Biobuf* b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  101. {
  102. int32_t ix, iy, i = 0, step_up = 0, skip = (4 - (((width % 8) + 1) / 2)) & 3;
  103. uint valH, valL;
  104. if(height > 0) { /* bottom-up */
  105. i = (height - 1) * width;
  106. step_up = -2 * width;
  107. } else
  108. height = -height;
  109. for(iy = height; iy; iy--, i += step_up) {
  110. for(ix = 0; ix < width; ) {
  111. valH = valL = Bgetc(b) & 0xff;
  112. valH >>= 4;
  113. buf[i] = clut[valH];
  114. i++; ix++;
  115. if(ix < width) {
  116. valL &= 0xf;
  117. buf[i] = clut[valL];
  118. i++; ix++;
  119. }
  120. }
  121. Bseek(b, skip, 1);
  122. }
  123. return 0;
  124. }
  125. /* Load a 4-Bit encoded BMP file (RLE4-compressed) */
  126. static int
  127. load_4C(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  128. {
  129. int32_t ix, iy = height -1;
  130. uint val, valS, skip;
  131. Rgb* p;
  132. while(iy >= 0) {
  133. ix = 0;
  134. while(ix < width) {
  135. val = (uint)Bgetc(b);
  136. if(0 != val) {
  137. valS = (uint)Bgetc(b);
  138. p = &buf[ix + iy * width];
  139. while(val--) {
  140. *p = clut[0xf & (valS >> 4)];
  141. p++;
  142. ix++;
  143. if(val != 0) {
  144. *p = clut[0xf & valS];
  145. p++;
  146. ix++;
  147. val--;
  148. }
  149. }
  150. } else {
  151. /* Special modes... */
  152. val = Bgetc(b);
  153. switch(val) {
  154. case 0: /* End-Of-Line detected */
  155. ix = width;
  156. iy--;
  157. break;
  158. case 1: /* End-Of-Picture detected -->> abort */
  159. ix = width;
  160. iy = -1;
  161. break;
  162. case 2: /* Position change detected */
  163. val = (uint)Bgetc(b);
  164. ix += val;
  165. val = (uint)Bgetc(b);
  166. iy -= val;
  167. break;
  168. default:/* Transparent data sequence detected */
  169. p = &buf[ix + iy * width];
  170. if((1 == (val & 3)) || (2 == (val & 3)))
  171. skip = 1;
  172. else
  173. skip = 0;
  174. while(val--) {
  175. valS = (uint)Bgetc(b);
  176. *p = clut[0xf & (valS >> 4)];
  177. p++;
  178. ix++;
  179. if(val != 0) {
  180. *p = clut[0xf & valS];
  181. p++;
  182. ix++;
  183. val--;
  184. }
  185. }
  186. if(skip)
  187. Bgetc(b);
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. return 0;
  194. }
  195. /* Load a 8-Bit encoded BMP file (uncompressed) */
  196. static int
  197. load_8T(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  198. {
  199. int32_t ix, iy, i = 0, step_up = 0, skip = (4 - (width % 4)) & 3;
  200. if(height > 0) { /* bottom-up */
  201. i = (height - 1) * width;
  202. step_up = -2 * width;
  203. } else
  204. height = -height;
  205. for(iy = height; iy; iy--, i += step_up) {
  206. for(ix = 0; ix < width; ix++, i++)
  207. buf[i] = clut[Bgetc(b) & 0xff];
  208. Bseek(b, skip, 1);
  209. }
  210. return 0;
  211. }
  212. /* Load a 8-Bit encoded BMP file (RLE8-compressed) */
  213. static int
  214. load_8C(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  215. {
  216. int32_t ix, iy = height -1;
  217. int val, valS, skip;
  218. Rgb* p;
  219. while(iy >= 0) {
  220. ix = 0;
  221. while(ix < width) {
  222. val = Bgetc(b);
  223. if(0 != val) {
  224. valS = Bgetc(b);
  225. p = &buf[ix + iy * width];
  226. while(val--) {
  227. *p = clut[valS];
  228. p++;
  229. ix++;
  230. }
  231. } else {
  232. /* Special modes... */
  233. val = Bgetc(b);
  234. switch(val) {
  235. case 0: /* End-Of-Line detected */
  236. ix = width;
  237. iy--;
  238. break;
  239. case 1: /* End-Of-Picture detected */
  240. ix = width;
  241. iy = -1;
  242. break;
  243. case 2: /* Position change detected */
  244. val = Bgetc(b);
  245. ix += val;
  246. val = Bgetc(b);
  247. iy -= val;
  248. break;
  249. default: /* Transparent (not compressed) sequence detected */
  250. p = &buf[ix + iy * width];
  251. if(val & 1)
  252. skip = 1;
  253. else
  254. skip = 0;
  255. while(val--) {
  256. valS = Bgetc(b);
  257. *p = clut[valS];
  258. p++;
  259. ix++;
  260. }
  261. if(skip)
  262. /* Align data stream */
  263. Bgetc(b);
  264. break;
  265. }
  266. }
  267. }
  268. }
  269. return 0;
  270. }
  271. /* Load a 16-Bit encoded BMP file (uncompressed) */
  272. static int
  273. load_16(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  274. {
  275. uint8_t c[2];
  276. int32_t ix, iy, i = 0, step_up = 0;
  277. if(height > 0) { /* bottom-up */
  278. i = (height - 1) * width;
  279. step_up = -2 * width;
  280. } else
  281. height = -height;
  282. if(clut) {
  283. unsigned mask_blue = (unsigned)clut[0].blue +
  284. ((unsigned)clut[0].green << 8);
  285. unsigned mask_green = (unsigned)clut[1].blue +
  286. ((unsigned)clut[1].green << 8);
  287. unsigned mask_red = (unsigned)clut[2].blue +
  288. ((unsigned)clut[2].green << 8);
  289. int shft_blue = msb((uint32_t)mask_blue) - 8;
  290. int shft_green = msb((uint32_t)mask_green) - 8;
  291. int shft_red = msb((uint32_t)mask_red) - 8;
  292. for(iy = height; iy; iy--, i += step_up)
  293. for(ix = 0; ix < width; ix++, i++) {
  294. unsigned val;
  295. Bread(b, c, sizeof(c));
  296. val = (unsigned)c[0] + ((unsigned)c[1] << 8);
  297. buf[i].alpha = 0;
  298. if(shft_blue >= 0)
  299. buf[i].blue = (uint8_t)((val & mask_blue) >> shft_blue);
  300. else
  301. buf[i].blue = (uint8_t)((val & mask_blue) << -shft_blue);
  302. if(shft_green >= 0)
  303. buf[i].green = (uint8_t)((val & mask_green) >> shft_green);
  304. else
  305. buf[i].green = (uint8_t)((val & mask_green) << -shft_green);
  306. if(shft_red >= 0)
  307. buf[i].red = (uint8_t)((val & mask_red) >> shft_red);
  308. else
  309. buf[i].red = (uint8_t)((val & mask_red) << -shft_red);
  310. }
  311. } else
  312. for(iy = height; iy; iy--, i += step_up)
  313. for(ix = 0; ix < width; ix++, i++) {
  314. Bread(b, c, sizeof(c));
  315. buf[i].blue = (uint8_t)((c[0] << 3) & 0xf8);
  316. buf[i].green = (uint8_t)(((((unsigned)c[1] << 6) +
  317. (((unsigned)c[0]) >> 2))) & 0xf8);
  318. buf[i].red = (uint8_t)((c[1] << 1) & 0xf8);
  319. }
  320. return 0;
  321. }
  322. /* Load a 24-Bit encoded BMP file (uncompressed) */
  323. static int
  324. load_24T(Biobuf* b, int32_t width, int32_t height, Rgb* buf)
  325. {
  326. int32_t ix, iy, i = 0, step_up = 0, skip = (4 - ((width * 3) % 4)) & 3;
  327. if(height > 0) { /* bottom-up */
  328. i = (height - 1) * width;
  329. step_up = -2 * width;
  330. } else
  331. height = -height;
  332. for(iy = height; iy; iy--, i += step_up) {
  333. for(ix = 0; ix < width; ix++, i++) {
  334. buf[i].alpha = 0;
  335. buf[i].blue = Bgetc(b);
  336. buf[i].green = Bgetc(b);
  337. buf[i].red = Bgetc(b);
  338. }
  339. Bseek(b, skip, 1);
  340. }
  341. return 0;
  342. }
  343. /* Load a 32-Bit encoded BMP file (uncompressed) */
  344. static int
  345. load_32(Biobuf *b, int32_t width, int32_t height, Rgb* buf, Rgb* clut)
  346. {
  347. uint8_t c[4];
  348. int32_t ix, iy, i = 0, step_up = 0;
  349. if(height > 0) { /* bottom-up */
  350. i = (height - 1) * width;
  351. step_up = -2 * width;
  352. } else
  353. height = -height;
  354. if(clut) {
  355. uint32_t mask_blue = (uint32_t)clut[0].blue +
  356. ((uint32_t)clut[0].green << 8) +
  357. ((uint32_t)clut[0].red << 16) +
  358. ((uint32_t)clut[0].alpha << 24);
  359. uint32_t mask_green = (uint32_t)clut[1].blue +
  360. ((uint32_t)clut[1].green << 8) +
  361. ((uint32_t)clut[1].red << 16) +
  362. ((uint32_t)clut[1].alpha << 24);
  363. uint32_t mask_red = (uint32_t)clut[2].blue +
  364. ((uint32_t)clut[2].green << 8) +
  365. ((uint32_t)clut[2].red << 16) +
  366. ((uint32_t)clut[2].alpha << 24);
  367. int shft_blue = msb(mask_blue) - 8;
  368. int shft_green = msb(mask_green) - 8;
  369. int shft_red = msb(mask_red) - 8;
  370. for(iy = height; iy; iy--, i += step_up)
  371. for(ix = 0; ix < width; ix++, i++) {
  372. uint32_t val;
  373. Bread(b, c, sizeof(c));
  374. val = (uint32_t)c[0] + ((uint32_t)c[1] << 8) +
  375. ((uint32_t)c[2] << 16) + ((uint32_t)c[1] << 24);
  376. buf[i].alpha = 0;
  377. if(shft_blue >= 0)
  378. buf[i].blue = (uint8_t)((val & mask_blue) >> shft_blue);
  379. else
  380. buf[i].blue = (uint8_t)((val & mask_blue) << -shft_blue);
  381. if(shft_green >= 0)
  382. buf[i].green = (uint8_t)((val & mask_green) >> shft_green);
  383. else
  384. buf[i].green = (uint8_t)((val & mask_green) << -shft_green);
  385. if(shft_red >= 0)
  386. buf[i].red = (uint8_t)((val & mask_red) >> shft_red);
  387. else
  388. buf[i].red = (uint8_t)((val & mask_red) << -shft_red);
  389. }
  390. } else
  391. for(iy = height; iy; iy--, i += step_up)
  392. for(ix = 0; ix < width; ix++, i++) {
  393. Bread(b, c, nelem(c));
  394. buf[i].blue = c[0];
  395. buf[i].green = c[1];
  396. buf[i].red = c[2];
  397. }
  398. return 0;
  399. }
  400. static Rgb*
  401. ReadBMP(Biobuf *b, int *width, int *height)
  402. {
  403. int colours, num_coltab = 0;
  404. Filehdr bmfh;
  405. Infohdr bmih;
  406. Rgb clut[256];
  407. Rgb* buf;
  408. bmfh.type = r16(b);
  409. if(bmfh.type != 0x4d42) /* signature must be 'BM' */
  410. sysfatal("bad magic number, not a BMP file");
  411. bmfh.size = r32(b);
  412. bmfh.reserved1 = r16(b);
  413. bmfh.reserved2 = r16(b);
  414. bmfh.offbits = r32(b);
  415. memset(&bmih, 0, sizeof(bmih));
  416. bmih.size = r32(b);
  417. if(bmih.size == 0x0c) { /* OS/2 1.x version */
  418. bmih.width = r16(b);
  419. bmih.height = r16(b);
  420. bmih.planes = r16(b);
  421. bmih.bpp = r16(b);
  422. bmih.compression = BMP_RGB;
  423. } else { /* Windows */
  424. bmih.width = r32(b);
  425. bmih.height = r32(b);
  426. bmih.planes = r16(b);
  427. bmih.bpp = r16(b);
  428. bmih.compression = r32(b);
  429. bmih.imagesize = r32(b);
  430. bmih.hres = r32(b);
  431. bmih.vres = r32(b);
  432. bmih.colours = r32(b);
  433. bmih.impcolours = r32(b);
  434. }
  435. if(bmih.bpp < 16) {
  436. /* load colour table */
  437. if(bmih.impcolours)
  438. num_coltab = (int)bmih.impcolours;
  439. else
  440. num_coltab = 1 << bmih.bpp;
  441. } else if(bmih.compression == BMP_BITFIELDS &&
  442. (bmih.bpp == 16 || bmih.bpp == 32))
  443. /* load bitmasks */
  444. num_coltab = 3;
  445. if(num_coltab) {
  446. int i;
  447. Bseek(b, bmih.size + Filehdrsz, 0);
  448. for(i = 0; i < num_coltab; i++) {
  449. clut[i].blue = (uint8_t)Bgetc(b);
  450. clut[i].green = (uint8_t)Bgetc(b);
  451. clut[i].red = (uint8_t)Bgetc(b);
  452. clut[i].alpha = (uint8_t)Bgetc(b);
  453. }
  454. }
  455. *width = bmih.width;
  456. *height = bmih.height;
  457. colours = bmih.bpp;
  458. Bseek(b, bmfh.offbits, 0);
  459. if ((buf = calloc(sizeof(Rgb), *width * abs(*height))) == nil)
  460. sysfatal("no memory");
  461. switch(colours) {
  462. case 1:
  463. load_1T(b, *width, *height, buf, clut);
  464. break;
  465. case 4:
  466. if(bmih.compression == BMP_RLE4)
  467. load_4C(b, *width, *height, buf, clut);
  468. else
  469. load_4T(b, *width, *height, buf, clut);
  470. break;
  471. case 8:
  472. if(bmih.compression == BMP_RLE8)
  473. load_8C(b, *width, *height, buf, clut);
  474. else
  475. load_8T(b, *width, *height, buf, clut);
  476. break;
  477. case 16:
  478. load_16(b, *width, *height, buf,
  479. bmih.compression == BMP_BITFIELDS ? clut : nil);
  480. break;
  481. case 24:
  482. load_24T(b, *width, *height, buf);
  483. break;
  484. case 32:
  485. load_32(b, *width, *height, buf,
  486. bmih.compression == BMP_BITFIELDS ? clut : nil);
  487. break;
  488. }
  489. return buf;
  490. }
  491. Rawimage**
  492. Breadbmp(Biobuf *bp, int colourspace)
  493. {
  494. Rawimage *a, **array;
  495. int c, width, height;
  496. uint8_t *r, *g, *b;
  497. Rgb *s, *e;
  498. Rgb *bmp;
  499. char ebuf[128];
  500. a = nil;
  501. bmp = nil;
  502. array = nil;
  503. USED(a);
  504. USED(bmp);
  505. if (colourspace != CRGB) {
  506. errstr(ebuf, sizeof ebuf); /* throw it away */
  507. werrstr("ReadRGB: unknown colour space %d", colourspace);
  508. return nil;
  509. }
  510. if ((bmp = ReadBMP(bp, &width, &height)) == nil)
  511. return nil;
  512. if ((a = calloc(sizeof(Rawimage), 1)) == nil)
  513. goto Error;
  514. for (c = 0; c < 3; c++)
  515. if ((a->chans[c] = calloc(width, height)) == nil)
  516. goto Error;
  517. if ((array = calloc(sizeof(Rawimage *), 2)) == nil)
  518. goto Error;
  519. array[0] = a;
  520. array[1] = nil;
  521. a->nchans = 3;
  522. a->chandesc = CRGB;
  523. a->chanlen = width * height;
  524. a->r = Rect(0, 0, width, height);
  525. s = bmp;
  526. e = s + width * height;
  527. r = a->chans[0];
  528. g = a->chans[1];
  529. b = a->chans[2];
  530. do {
  531. *r++ = s->red;
  532. *g++ = s->green;
  533. *b++ = s->blue;
  534. }while(++s < e);
  535. free(bmp);
  536. return array;
  537. Error:
  538. if (a)
  539. for (c = 0; c < 3; c++)
  540. if (a->chans[c])
  541. free(a->chans[c]);
  542. if (a)
  543. free(a);
  544. if (array)
  545. free(array);
  546. if (bmp)
  547. free(bmp);
  548. return nil;
  549. }
  550. Rawimage**
  551. readbmp(int fd, int colorspace)
  552. {
  553. Rawimage * *a;
  554. Biobuf b;
  555. if (Binit(&b, fd, OREAD) < 0)
  556. return nil;
  557. a = Breadbmp(&b, colorspace);
  558. Bterm(&b);
  559. return a;
  560. }