Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BMP3 exporter ignores desired image depth when lower image depth is possible #7028

Open
ninakali opened this issue Jan 14, 2024 · 12 comments
Open

Comments

@ninakali
Copy link

ImageMagick version

7.1.1-3

Operating system

MacOS

Operating system, version and so on

MacOS 13.0, aarch64. ImageMagick from brew for x86_64 running through Rosetta

Description

For some rare bizarre old systems and programs, BMP images with palette must have precise image depth (4bpp or 8bpp). I was hoping to convert images to this format with ImageMagick. Unfortunately, it looks like if the source image has palette that is smaller than depth specified as a target, the ImageMagick will generate BMP file with smaller image depth than requested. This might be nice for creating smaller BMP files, but doesn't help when it comes to retrocomputing or specific applications.

Steps to Reproduce

File white.png is a pure white image. File palette.png has 16 colors.
The target is bmp3 with depth=8 and colors=256.
Expectations: PC bitmap 8bpp
Reality: PC bitmap 1bpp and 4bpp

$ convert white.png -define bmp:format=bmp3 -depth 8 -colors 256 BMP3:white.bmp
$ convert palette.png -define bmp:format=bmp3 -depth 8 -colors 256 BMP3:palette.bmp
$ file white.bmp
white.bmp: PC bitmap, Windows 3.x format, 160 x 100 x 1, image size 2000, resolution 196 x 236 px/m, 2 important colors, cbSize 2062, bits offset 62
$ file palette.bmp
palette.bmp: PC bitmap, Windows 3.x format, 4 x 4 x 4, image size 16, resolution 11811 x 11811 px/m, 16 important colors, cbSize 806, bits offset 118

Images

white
palette

@fmw42
Copy link

fmw42 commented Jan 14, 2024

On my Mac using:

magick white.png -depth 8 +dither -colors 256 BMP3:white.bmp

I get a bilevel 1-bit result

 Filename: white.bmp
  Permissions: rw-r--r--
  Format: BMP3 (Microsoft Windows bitmap image (V3))
  Class: PseudoClass
  Geometry: 160x100+0+0
  Resolution: 1.96x2.36
  Print size: 81.6327x42.3729
  Units: PixelsPerCentimeter
  Colorspace: sRGB
  Type: Bilevel
  Base type: Undefined
  Endianness: Undefined
  Depth: 1-bit
  Channel depth:
    red: 1-bit
    green: 1-bit
    blue: 1-bit

What are you expecting? Perhaps your "file" program has limitation.

Using Exiftool also shows 1-bit image

exiftool -s -ee -g1 -u -D white.bmp
---- ExifTool ----
    - ExifToolVersion                 : 12.56
---- System ----
    - FileName                        : white.bmp
    - Directory                       : .
    - FileSize                        : 2.1 kB
    - FileModifyDate                  : 2024:01:14 12:46:28-08:00
    - FileAccessDate                  : 2024:01:14 12:46:30-08:00
    - FileInodeChangeDate             : 2024:01:14 12:46:28-08:00
    - FilePermissions                 : -rw-r--r--
---- File ----
    - FileType                        : BMP
    - FileTypeExtension               : bmp
    - MIMEType                        : image/bmp
    0 BMPVersion                      : Windows V3
    4 ImageWidth                      : 160
    8 ImageHeight                     : 100
   12 Planes                          : 1
   14 BitDepth                        : 1
   16 Compression                     : None
   20 ImageLength                     : 2000
   24 PixelsPerMeterX                 : 196
   28 PixelsPerMeterY                 : 236
   32 NumColors                       : 2
   36 NumImportantColors              : 2
---- Composite ----
    - ImageSize                       : 160x100
    - Megapixels                      : 0.016

@ninakali
Copy link
Author

Exactly, despite depth being set to 8, the resulting image is 1 bpp. Interestingly, adding +matte will "upgrade" the file to 24 bpp. That sounds like a bug in exporter to me.

@fmw42
Copy link

fmw42 commented Jan 14, 2024

I believe Imagemagick will generally reduce the depth to the number of actual colors in the image.

Add -type truecolor gives 8-bit depth but only actually 1-bit in terms of colors.

magick white.png -depth 8 +dither -colors 256 -type truecolor BMP3:white.bmp

Image:
  Filename: white.bmp
  Permissions: rw-r--r--
  Format: BMP3 (Microsoft Windows bitmap image (V3))
  Class: DirectClass
  Geometry: 160x100+0+0
  Resolution: 1.96x2.36
  Print size: 81.6327x42.3729
  Units: PixelsPerCentimeter
  Colorspace: sRGB
  Type: Bilevel
  Base type: Undefined
  Endianness: Undefined
  Depth: 8/1-bit

@ninakali
Copy link
Author

That is a shame, the last thing I want is to write my own BMP encoder:(

I tried to use Netscape palette for the images, so it would have 200+ colours in the palette area, but alas, the resulting image is still 1bpp or 4bpp (for palette.png).

@fmw42
Copy link

fmw42 commented Jan 14, 2024

I am no expert. An Imagemagick developer might comment further.

@snibgo
Copy link

snibgo commented Jan 14, 2024

-colors 256 is an operation that will ensure the image contains no more than 256 different colours. In your commands, the images already contain fewer colours, so the operation does nothing.

I'm not sure what output you want. A BMP with a palette? Where each palette entry contains 8-bit/channel colours? Perhaps you want 256 entries in the palette, even though the image has only one colour. I don't think IM can do that.

@ninakali
Copy link
Author

Correct, I want a paletted image in 4bpp or 8bpp format, even when the image in its current state needs less colors. I believe depth parameter is the one that should specify the depth of the resulting image, but it doesn't affect the outcome. I want to note that paletted BMP that doesn't use all the palette colors is a totally valid use-case for BMP.

@fmw42
Copy link

fmw42 commented Jan 14, 2024

What colors would you want in the palette to fill it up?

@ninakali
Copy link
Author

The ones from the palette.png are a must for my use case. Having an empty BMP with web-safe colors in the palette is also not a bad idea. Having #000000 or #ffffff as filler colours is also fine. Imagine that the source image has 17 colours; IM will export it as 8bpp palletted BMP with 256 palette entries; where would it get the colours for the rest of the palette?

@snibgo
Copy link

snibgo commented Jan 14, 2024

If you have -compress RLE for a paletted output, you will get 256 entries. For example:

magick -size 200x200 xc:khaki -type palette -compress RLE x.bmp

@ninakali
Copy link
Author

This is quite interesting, thanks! Unfortunately, the tool I'm aiming for doesn't support RLE.

@snibgo
Copy link

snibgo commented Jan 15, 2024

I don't think there is any other way to force a 256-entry BMP palette. If you build IM yourself, you could patch coders/bmp.c, perhaps by changing:

        if (image_info->compression == RLECompression)
          bmp_info.bits_per_pixel=8;

... to:

        if (image_info->compression == RLECompression || 1==1)
          bmp_info.bits_per_pixel=8;

I haven't tested this patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants