SaveImage() often writes very strange BMPs. What "strange" actually means differs and is based on the color depth of the source image and the target color depth.
Let's start creating some test images in "%TMP%\PureBasic_BMP_Bug\":
Code: Select all
UsePNGImageEncoder()
CreateImage(0,32,32,32)
CreateImage(1,32,32,24)
For image = 0 To 1
StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
c = $11111111
For y = 31 To 0 Step -1 ; BMPs are stored "bottom line first", so "Step -1" makes hex code inspection easier
For x = 0 To 31
Plot(x, y, c)
If c <> $FFFFFFFF
c + $11111111
Else
c = $11111111
EndIf
Next
Next
StopDrawing()
Next
dir$ = GetTemporaryDirectory() + "PureBasic_BMP_Bug" + #PS$
CreateDirectory( dir$ )
SaveImage(0,dir$+"bmp_32-to-32.bmp", #PB_ImagePlugin_BMP, 0, 32)
SaveImage(0,dir$+"bmp_32-to-24.bmp", #PB_ImagePlugin_BMP, 0, 24)
SaveImage(0,dir$+"bmp_32-to-8.bmp" , #PB_ImagePlugin_BMP, 0, 8)
SaveImage(0,dir$+"bmp_32-to-4.bmp" , #PB_ImagePlugin_BMP, 0, 4)
SaveImage(0,dir$+"bmp_32-to-1.bmp" , #PB_ImagePlugin_BMP, 0, 1)
SaveImage(1,dir$+"bmp_24-to-32.bmp", #PB_ImagePlugin_BMP, 0, 32)
SaveImage(1,dir$+"bmp_24-to-24.bmp", #PB_ImagePlugin_BMP, 0, 24)
SaveImage(1,dir$+"bmp_24-to-8.bmp" , #PB_ImagePlugin_BMP, 0, 8)
SaveImage(1,dir$+"bmp_24-to-4.bmp" , #PB_ImagePlugin_BMP, 0, 4)
SaveImage(1,dir$+"bmp_24-to-1.bmp" , #PB_ImagePlugin_BMP, 0, 1)
Although "bmp_32-to-32.bmp" looks good, as well as all the "bmp_24-to-*.bmp" files, if you take a deeper look, then ONLY "bmp_24-to-24.bmp" and "bmp_24-to-32.bmp" are actually completely correct. The Rest is in one or another way messed up...
So let's brake it down and inspect the files with any hex editor (but I won't mention the obvious wrong colors).
bmp_32-to-32.bmp
The alpha channel is saved, although (by specification) the 4th byte is "reserved" and "should be 0".
The funny thing is, that the alpha channel is stored when using SaveImage(), but gets stripped away when using LoadImage().
Since you can find some 32bit BMPs in the wild, that use the "reserved" byte for alpha channel (although this is against the specification), I personally would prefer to simply allow LoadImage() also to treat the "reserved" byte as the alpha channel, as long as the "reserved" bytes are not all together zeroes (This is exactly how MS handles 32bit bitmaps inside ICO files! Follow this link and see line 6).
bmp_32-to-24
This is completely nuts...
The pixel data start with this:
EF EF EF E1 E1 E1 D6 D6 D6 ...
While it should start like this:
11 11 11 22 22 22 33 33 33 ...
bmp_32-to-1
The color palette looks like this:
00 00 00 77 FF FF FF 00
So the first color again has $77 written in the "reserved" byte, while the second color looks as expected.
The pixel array is also very strange: It consists of %1 from beginning to end. So only the second color is used.
bmp_32-to-4
The color palette looks like this:
C3 C3 C3 77
C5 C5 C5 00
C5 C5 C5 00
C5 C5 C5 00
C7 C7 C7 00
D2 D2 D2 00
D4 D4 D4 00
D5 D5 D5 00
D7 D7 D7 00
E0 E0 E0 00
E4 E4 E4 00
E6 E6 E6 00
F0 F0 F0 77
F0 F0 F0 00
F8 F8 F8 00
FC FC FC 00
The source image was composed out of 15 colors ($11111111, $22222222, ..., $FFFFFFFF). So each palette color should have a distinct value, except a single one (the unused 16th color) which could basically have any random value. In reality some palette colors have multiple "twins".
Also very strange is that two palette colors have the "reserved" byte set to $77, while the rest has the expected $00.
bmp_32-to-8
Similar problems as with "bmp_32-to-4". The color palette has some non-zero "reserved" bytes, while most values are correctly zeroes. The distribution of these non-zero bytes seem completely random.
bmp_24-to-32
Everything's OK here! All "reserved" bytes have a value of zero and the actual color values are correct!
bmp_24-to-24
Everything's OK here! Three byte per color and every color value is correct!
bmp_24-to-1
Same wrong color palette as in "bmp_32-to-1", but the pixel array correctly refers to both colors in the palette!
The color palette looks like this:
00 00 00 77 FF FF FF 00
So the first color again has $77 written in the "reserved" byte, while the second color looks as expected.
bmp_24-to-4
The color palette looks like this:
19 19 19 77
1B 1B 1B 00
25 25 25 00
30 30 30 00
46 46 46 00
54 54 54 00
66 66 66 00
77 77 77 00
88 88 88 00
99 99 99 00
AA AA AA 00
BC BC BC 00
D0 D0 D0 77
DD DD DD 00
EE EE EE 00
F3 F3 F3 00
Again, you have the "reserved" byte set to $77 for two colors.
The color distribution also seems quite strange. The source image was composed out of 15 colors ($111111, $222222, ..., $FFFFFF). So each palette color should have a distinct value, except a single one (the unused 16th color) which could basically have any random value. In reality the darkest color starts with $191919 and the lightest color ends at $F3F3F3. So the 15 source colors are distributed over 16 palette colors, while start and endpoint are slightly off.
bmp_24-to-8
As always you have some "reserved" byte set to $77, but this time you have some other strange values like $65, $10 or $E0 mixed in, while still most palette colors have the correct $00.
The palette has all of the 15 source colors. But in addition on one hand it has a lot of redundancies (e.g. 20 times the color $111111) and some strange "inbetween" values (e.g. the following in a row: $111111, $121212, $141414, $171717).