3

So, I'm trying to understand how PNG to BMP conversion actually takes place. I created the following 8x8 pixel PNG using a tool online:

enter image description here

I then performed a conversion using the ImageMagik tool in OSX terminal:

$ convert -monochrome pic.png pic.bmp

Afterwards, I did a hexdump of the image:

$ hexdump -C pic.bmp 00000000 42 4d 4a 01 00 00 00 00 00 00 8a 00 00 00 7c 00 |BMJ...........|.| 00000010 00 00 08 00 00 00 08 00 00 00 01 00 18 00 00 00 |................| 00000020 00 00 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 ff 00 00 ff 00 00 ff 00 |................| 00000040 00 00 00 00 00 ff 42 47 52 73 8f c2 f5 28 51 b8 |......BGRs...(Q.| 00000050 1e 15 1e 85 eb 01 33 33 33 13 66 66 66 26 66 66 |......333.fff&ff| 00000060 66 06 99 99 99 09 3d 0a d7 03 28 5c 8f 32 00 00 |f.....=...(\.2..| 00000070 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff |................| 00000090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * 00000130 ff ff 00 00 00 ff ff ff ff ff ff ff ff ff ff ff |................| 00000140 ff ff ff ff ff ff ff ff ff ff |..........| 0000014a

So, obviously we have a BMP header from 0x00 - 0x8C. Then we have FF for white pixels and 00 for black. That all makes sense, but the structure of the output doesn't. So far, it seems that there is a 3 to 1 ratio. 3 bytes per pixel. I'm assuming this means black, white, no-color?

I need to fully understand why there are 3 bytes per pixel instead of 2. Ideally, I would like a binary 1 or 0 for each pixel instead. Is there a way to do this? And if not, can someone please explain the layout of bytes? Specifically: Why are the 3 00s at 0x132 - 0x134 and not the very beginning?

Thanks

JohnnyStarr
  • 619
  • 8
  • 21
  • probably a color bmp, which means 24bits-per-color (8bit red, 8bit green, 8bit blue). if you want a true B&W bitmap, you have to output the appropriate bmp header options to say it's B&W. – Marc B May 19 '16 at 16:54
  • The BMP file format is well explained on its Wikipedia page. Why not start there? For one, it tells you what byte in that header indicates the bit depth. – Jongware May 19 '16 at 17:29

3 Answers3

5

Imagemagick, in fact, does support 1-bit BMP, if using either BMP3 or BMP2 formats, but not BMP4 which is just BMP. So if you want 1-bit depth per channel, then do

Input:

enter image description here

convert image.png -depth 1 BMP3:result.bmp

enter image description here

If you want a 1-bit depth for the whole image (i.e. binary), then do

convert image.png -depth 1 -type bilevel BMP3:result2.bmp

enter image description here

Or

convert image.png -depth 1 -threshold 50% BMP3:result3.bmp

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80
2

I'm not sure which question this will answer, but from the Usage docs

IM can not produce BMP's at depth levels other than 8. However you can use NetPBM image processing set to do the final conversion to other depth levels (This needs at least a Q16 version of IM)...

So if we leverage NetPBM

$ convert pic.png -depth 1  ppm:- | hexdump

Which gives (Note the values are 0 & 1, but you still have a RGB channels)

0000000 50 36 0a 38 20 38 0a 31 0a 00 00 00 01 01 01 01
0000010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
*
00000c0 01 01 01 01 01 01 01 01 01                     
00000c9

So a workaround my be as simple as

$ convert pic.png -depth 1  ppm:- | pnmdepth 1 | ppm2bmp > pic.bmp
emcconville
  • 23,800
  • 4
  • 50
  • 66
0

On Fedora 27 that command is:

$ convert pic.png -depth 1  ppm:- | pnmdepth 1 | ppmtobmp > pic.bmp

You need:

$  dnf install netpbm-progs
dnaldoog
  • 39
  • 2