BMPParser.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #include "BMPParser.h"
  2. #include <cassert>
  3. using namespace std;
  4. using namespace BMPParser;
  5. #define MAX_IMG_SIZE 10000
  6. #define E(cond, msg) if(cond) return setErr(msg)
  7. #define EU(cond, msg) if(cond) return setErrUnsupported(msg)
  8. #define EX(cond, msg) if(cond) return setErrUnknown(msg)
  9. #define I1() get<char>()
  10. #define U1() get<uint8_t>()
  11. #define I2() get<int16_t>()
  12. #define U2() get<uint16_t>()
  13. #define I4() get<int32_t>()
  14. #define U4() get<uint32_t>()
  15. #define I1UC() get<char, false>()
  16. #define U1UC() get<uint8_t, false>()
  17. #define I2UC() get<int16_t, false>()
  18. #define U2UC() get<uint16_t, false>()
  19. #define I4UC() get<int32_t, false>()
  20. #define U4UC() get<uint32_t, false>()
  21. #define CHECK_OVERRUN(ptr, size, type) \
  22. if((ptr) + (size) - data > len){ \
  23. setErr("unexpected end of file"); \
  24. return type(); \
  25. }
  26. Parser::~Parser(){
  27. data = nullptr;
  28. ptr = nullptr;
  29. if(imgd){
  30. delete[] imgd;
  31. imgd = nullptr;
  32. }
  33. }
  34. void Parser::parse(uint8_t *buf, int bufSize, uint8_t *format){
  35. assert(status == Status::EMPTY);
  36. data = ptr = buf;
  37. len = bufSize;
  38. // Start parsing file header
  39. setOp("file header");
  40. // File header signature
  41. string fhSig = getStr(2);
  42. string temp = "file header signature";
  43. EU(fhSig == "BA", temp + " \"BA\"");
  44. EU(fhSig == "CI", temp + " \"CI\"");
  45. EU(fhSig == "CP", temp + " \"CP\"");
  46. EU(fhSig == "IC", temp + " \"IC\"");
  47. EU(fhSig == "PT", temp + " \"PT\"");
  48. EX(fhSig != "BM", temp); // BM
  49. // Length of the file should not be larger than `len`
  50. E(U4() > static_cast<uint32_t>(len), "inconsistent file size");
  51. // Skip unused values
  52. skip(4);
  53. // Offset where the pixel array (bitmap data) can be found
  54. auto imgdOffset = U4();
  55. // Start parsing DIB header
  56. setOp("DIB header");
  57. // Prepare some variables in case they are needed
  58. uint32_t compr = 0;
  59. uint32_t redShift = 0, greenShift = 0, blueShift = 0, alphaShift = 0;
  60. uint32_t redMask = 0, greenMask = 0, blueMask = 0, alphaMask = 0;
  61. double redMultp = 0, greenMultp = 0, blueMultp = 0, alphaMultp = 0;
  62. /**
  63. * Type of the DIB (device-independent bitmap) header
  64. * is determined by its size. Most BMP files use BITMAPINFOHEADER.
  65. */
  66. auto dibSize = U4();
  67. temp = "DIB header";
  68. EU(dibSize == 64, temp + " \"OS22XBITMAPHEADER\"");
  69. EU(dibSize == 16, temp + " \"OS22XBITMAPHEADER\"");
  70. uint32_t infoHeader = dibSize == 40 ? 1 :
  71. dibSize == 52 ? 2 :
  72. dibSize == 56 ? 3 :
  73. dibSize == 108 ? 4 :
  74. dibSize == 124 ? 5 : 0;
  75. // BITMAPCOREHEADER, BITMAP*INFOHEADER, BITMAP*HEADER
  76. auto isDibValid = dibSize == 12 || infoHeader;
  77. EX(!isDibValid, temp);
  78. // Image width
  79. w = dibSize == 12 ? U2() : I4();
  80. E(!w, "image width is 0");
  81. E(w < 0, "negative image width");
  82. E(w > MAX_IMG_SIZE, "too large image width");
  83. // Image height (specification allows negative values)
  84. h = dibSize == 12 ? U2() : I4();
  85. E(!h, "image height is 0");
  86. E(h > MAX_IMG_SIZE, "too large image height");
  87. bool isHeightNegative = h < 0;
  88. if(isHeightNegative) h = -h;
  89. // Number of color planes (must be 1)
  90. E(U2() != 1, "number of color planes must be 1");
  91. // Bits per pixel (color depth)
  92. auto bpp = U2();
  93. auto isBppValid = bpp == 1 || bpp == 4 || bpp == 8 || bpp == 16 || bpp == 24 || bpp == 32;
  94. EU(!isBppValid, "color depth");
  95. // Calculate image data size and padding
  96. uint32_t expectedImgdSize = (((w * bpp + 31) >> 5) << 2) * h;
  97. uint32_t rowPadding = (-w * bpp & 31) >> 3;
  98. uint32_t imgdSize = 0;
  99. // Color palette data
  100. uint8_t* paletteStart = nullptr;
  101. uint32_t palColNum = 0;
  102. if(infoHeader){
  103. // Compression type
  104. compr = U4();
  105. temp = "compression type";
  106. EU(compr == 1, temp + " \"BI_RLE8\"");
  107. EU(compr == 2, temp + " \"BI_RLE4\"");
  108. EU(compr == 4, temp + " \"BI_JPEG\"");
  109. EU(compr == 5, temp + " \"BI_PNG\"");
  110. EU(compr == 6, temp + " \"BI_ALPHABITFIELDS\"");
  111. EU(compr == 11, temp + " \"BI_CMYK\"");
  112. EU(compr == 12, temp + " \"BI_CMYKRLE8\"");
  113. EU(compr == 13, temp + " \"BI_CMYKRLE4\"");
  114. // BI_RGB and BI_BITFIELDS
  115. auto isComprValid = compr == 0 || compr == 3;
  116. EX(!isComprValid, temp);
  117. // Ensure that BI_BITFIELDS appears only with 16-bit or 32-bit color
  118. E(compr == 3 && !(bpp == 16 || bpp == 32), "compression BI_BITFIELDS can be used only with 16-bit and 32-bit color depth");
  119. // Size of the image data
  120. imgdSize = U4();
  121. // Horizontal and vertical resolution (ignored)
  122. skip(8);
  123. // Number of colors in the palette or 0 if no palette is present
  124. palColNum = U4();
  125. EU(palColNum && bpp > 8, "color palette and bit depth combination");
  126. if(palColNum) paletteStart = data + dibSize + 14;
  127. // Number of important colors used or 0 if all colors are important (generally ignored)
  128. skip(4);
  129. if(infoHeader >= 2){
  130. // If BI_BITFIELDS are used, calculate masks, otherwise ignore them
  131. if(compr == 3){
  132. calcMaskShift(redShift, redMask, redMultp);
  133. calcMaskShift(greenShift, greenMask, greenMultp);
  134. calcMaskShift(blueShift, blueMask, blueMultp);
  135. if(infoHeader >= 3) calcMaskShift(alphaShift, alphaMask, alphaMultp);
  136. if(status == Status::ERROR) return;
  137. }else{
  138. skip(16);
  139. }
  140. // Ensure that the color space is LCS_WINDOWS_COLOR_SPACE or sRGB
  141. if(infoHeader >= 4 && !palColNum){
  142. string colSpace = getStr(4, 1);
  143. EU(colSpace != "Win " && colSpace != "sRGB", "color space \"" + colSpace + "\"");
  144. }
  145. }
  146. }
  147. // Skip to the image data (there may be other chunks between, but they are optional)
  148. E(ptr - data > imgdOffset, "image data overlaps with another structure");
  149. ptr = data + imgdOffset;
  150. // Start parsing image data
  151. setOp("image data");
  152. if(!imgdSize){
  153. // Value 0 is allowed only for BI_RGB compression type
  154. E(compr != 0, "missing image data size");
  155. imgdSize = expectedImgdSize;
  156. }else{
  157. E(imgdSize < expectedImgdSize, "invalid image data size");
  158. }
  159. // Ensure that all image data is present
  160. E(ptr - data + imgdSize > len, "not enough image data");
  161. // Direction of reading rows
  162. int yStart = h - 1;
  163. int yEnd = -1;
  164. int dy = isHeightNegative ? 1 : -1;
  165. // In case of negative height, read rows backward
  166. if(isHeightNegative){
  167. yStart = 0;
  168. yEnd = h;
  169. }
  170. // Allocate output image data array
  171. int buffLen = w * h << 2;
  172. imgd = new (nothrow) uint8_t[buffLen];
  173. E(!imgd, "unable to allocate memory");
  174. // Prepare color values
  175. uint8_t color[4] = {0};
  176. uint8_t &red = color[0];
  177. uint8_t &green = color[1];
  178. uint8_t &blue = color[2];
  179. uint8_t &alpha = color[3];
  180. // Check if pre-multiplied alpha is used
  181. bool premul = format ? format[4] : 0;
  182. // Main loop
  183. for(int y = yStart; y != yEnd; y += dy){
  184. // Use in-byte offset for bpp < 8
  185. uint8_t colOffset = 0;
  186. uint8_t cval = 0;
  187. uint32_t val = 0;
  188. for(int x = 0; x != w; x++){
  189. // Index in the output image data
  190. int i = (x + y * w) << 2;
  191. switch(compr){
  192. case 0: // BI_RGB
  193. switch(bpp){
  194. case 1:
  195. if(colOffset) ptr--;
  196. cval = (U1UC() >> (7 - colOffset)) & 1;
  197. if(palColNum){
  198. uint8_t* entry = paletteStart + (cval << 2);
  199. blue = get<uint8_t>(entry);
  200. green = get<uint8_t>(entry + 1);
  201. red = get<uint8_t>(entry + 2);
  202. if(status == Status::ERROR) return;
  203. }else{
  204. red = green = blue = cval ? 255 : 0;
  205. }
  206. alpha = 255;
  207. colOffset = (colOffset + 1) & 7;
  208. break;
  209. case 4:
  210. if(colOffset) ptr--;
  211. cval = (U1UC() >> (4 - colOffset)) & 15;
  212. if(palColNum){
  213. uint8_t* entry = paletteStart + (cval << 2);
  214. blue = get<uint8_t>(entry);
  215. green = get<uint8_t>(entry + 1);
  216. red = get<uint8_t>(entry + 2);
  217. if(status == Status::ERROR) return;
  218. }else{
  219. red = green = blue = cval << 4;
  220. }
  221. alpha = 255;
  222. colOffset = (colOffset + 4) & 7;
  223. break;
  224. case 8:
  225. cval = U1UC();
  226. if(palColNum){
  227. uint8_t* entry = paletteStart + (cval << 2);
  228. blue = get<uint8_t>(entry);
  229. green = get<uint8_t>(entry + 1);
  230. red = get<uint8_t>(entry + 2);
  231. if(status == Status::ERROR) return;
  232. }else{
  233. red = green = blue = cval;
  234. }
  235. alpha = 255;
  236. break;
  237. case 16:
  238. // RGB555
  239. val = U1UC();
  240. val |= U1UC() << 8;
  241. red = (val >> 10) << 3;
  242. green = (val >> 5) << 3;
  243. blue = val << 3;
  244. alpha = 255;
  245. break;
  246. case 24:
  247. blue = U1UC();
  248. green = U1UC();
  249. red = U1UC();
  250. alpha = 255;
  251. break;
  252. case 32:
  253. blue = U1UC();
  254. green = U1UC();
  255. red = U1UC();
  256. if(infoHeader >= 3){
  257. alpha = U1UC();
  258. }else{
  259. alpha = 255;
  260. skip(1);
  261. }
  262. break;
  263. }
  264. break;
  265. case 3: // BI_BITFIELDS
  266. uint32_t col = bpp == 16 ? U2UC() : U4UC();
  267. red = ((col >> redShift) & redMask) * redMultp + .5;
  268. green = ((col >> greenShift) & greenMask) * greenMultp + .5;
  269. blue = ((col >> blueShift) & blueMask) * blueMultp + .5;
  270. alpha = alphaMask ? ((col >> alphaShift) & alphaMask) * alphaMultp + .5 : 255;
  271. break;
  272. }
  273. /**
  274. * Pixel format:
  275. * red,
  276. * green,
  277. * blue,
  278. * alpha,
  279. * is alpha pre-multiplied
  280. * Default is [0, 1, 2, 3, 0]
  281. */
  282. if(premul && alpha != 255){
  283. double a = alpha / 255.;
  284. red = static_cast<uint8_t>(red * a + .5);
  285. green = static_cast<uint8_t>(green * a + .5);
  286. blue = static_cast<uint8_t>(blue * a + .5);
  287. }
  288. if(format){
  289. imgd[i] = color[format[0]];
  290. imgd[i + 1] = color[format[1]];
  291. imgd[i + 2] = color[format[2]];
  292. imgd[i + 3] = color[format[3]];
  293. }else{
  294. imgd[i] = red;
  295. imgd[i + 1] = green;
  296. imgd[i + 2] = blue;
  297. imgd[i + 3] = alpha;
  298. }
  299. }
  300. // Skip unused bytes in the current row
  301. skip(rowPadding);
  302. }
  303. if(status == Status::ERROR) return;
  304. status = Status::OK;
  305. };
  306. void Parser::clearImgd(){ imgd = nullptr; }
  307. int32_t Parser::getWidth() const{ return w; }
  308. int32_t Parser::getHeight() const{ return h; }
  309. uint8_t *Parser::getImgd() const{ return imgd; }
  310. Status Parser::getStatus() const{ return status; }
  311. string Parser::getErrMsg() const{
  312. return "Error while processing " + getOp() + " - " + err;
  313. }
  314. template <typename T, bool check> inline T Parser::get(){
  315. if(check)
  316. CHECK_OVERRUN(ptr, sizeof(T), T);
  317. T val = *(T*)ptr;
  318. ptr += sizeof(T);
  319. return val;
  320. }
  321. template <typename T, bool check> inline T Parser::get(uint8_t* pointer){
  322. if(check)
  323. CHECK_OVERRUN(pointer, sizeof(T), T);
  324. T val = *(T*)pointer;
  325. return val;
  326. }
  327. string Parser::getStr(int size, bool reverse){
  328. CHECK_OVERRUN(ptr, size, string);
  329. string val = "";
  330. while(size--){
  331. if(reverse) val = string(1, static_cast<char>(*ptr++)) + val;
  332. else val += static_cast<char>(*ptr++);
  333. }
  334. return val;
  335. }
  336. inline void Parser::skip(int size){
  337. CHECK_OVERRUN(ptr, size, void);
  338. ptr += size;
  339. }
  340. void Parser::calcMaskShift(uint32_t& shift, uint32_t& mask, double& multp){
  341. mask = U4();
  342. shift = 0;
  343. if(mask == 0) return;
  344. while(~mask & 1){
  345. mask >>= 1;
  346. shift++;
  347. }
  348. E(mask & (mask + 1), "invalid color mask");
  349. multp = 255. / mask;
  350. }
  351. void Parser::setOp(string val){
  352. if(status != Status::EMPTY) return;
  353. op = val;
  354. }
  355. string Parser::getOp() const{
  356. return op;
  357. }
  358. void Parser::setErrUnsupported(string msg){
  359. setErr("unsupported " + msg);
  360. }
  361. void Parser::setErrUnknown(string msg){
  362. setErr("unknown " + msg);
  363. }
  364. void Parser::setErr(string msg){
  365. if(status != Status::EMPTY) return;
  366. err = msg;
  367. status = Status::ERROR;
  368. }
  369. string Parser::getErr() const{
  370. return err;
  371. }