Skip to content

Commit 9d2f887

Browse files
author
MaximDude
committed
Set up BMP file writer, partly functional
Works for blanks and actually creates indexed bmps with proper palettes but leaves strange artifacts and hangs when creating pixel arrays for non-blanks
1 parent ec499b5 commit 9d2f887

File tree

1 file changed

+107
-3
lines changed

1 file changed

+107
-3
lines changed

cccp-bender-main.bmx

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Import MaxGUI.Drivers
99
Import BRL.Max2D
1010
Import BRL.Pixmap
1111
Import BRL.PNGLoader
12+
Import BRL.Stream
13+
Import BRL.EndianStream
1214

1315
'Version
1416
Global appVersion:String = "1.1"
@@ -19,8 +21,6 @@ Rem
1921
EndRem
2022

2123
Type TBitmapIndex
22-
Const GFX_PAL:Byte=0
23-
2424
'Color Value Bytes
2525
Global palR:Byte[256]
2626
Global palG:Byte[256]
@@ -40,6 +40,108 @@ Type TBitmapIndex
4040
EndIf
4141
EndFunction
4242

43+
'Indexed Bitmap File Writer
44+
Function FPixmapToIndexedBitmap(image:TPixmap,filename:String)
45+
'Variables
46+
Local bmpWidth:Int, bmpWidthM4:Int
47+
Local bmpHeight:Int
48+
Local bmpSizeTotal:Int, bmpSizeTotalM4:Int
49+
Local paletteIndex:Int = 0
50+
51+
'Dimensions calc
52+
bmpWidth = PixmapWidth(image)
53+
bmpWidthM4 = ((bmpWidth + 3) / 4) * 4
54+
bmpHeight = PixmapHeight(image)
55+
56+
'Filesize calc
57+
bmpSizeTotal = (14 + 40) + (256 * 4) + (bmpWidthM4 * bmpHeight)
58+
bmpSizeTotalM4 = ((bmpSizeTotal + 3) / 4) * 4
59+
60+
'Begin writing BMP file manually
61+
Local dataStream:TStream = WriteFile(filename)
62+
63+
'------ Bitmap File Header
64+
'Header file data is stored in little-endian format (least-significant byte first)
65+
dataStream = LittleEndianStream(dataStream)
66+
67+
WriteShort(dataStream,19778) 'File ID (2 bytes (short)) - 19778 (deci) or 42 4D (hex) or BM (ascii) for bitmap
68+
WriteInt(dataStream,bmpSizeTotalM4) 'File Size (4 bytes (signed int))
69+
WriteShort(dataStream,0) 'Reserved (2 bytes)
70+
WriteShort(dataStream,0) 'Reserved (2 bytes)
71+
WriteInt(dataStream,54) 'Pixel Array Offset (4 bytes) - pixel array starts at 54th byte
72+
'Print("wrote header")
73+
74+
'CloseStream(headerStream)
75+
76+
'------ DIB Header (File Info)
77+
'dataStream = BigEndianStream(dataStream)
78+
79+
WriteInt(dataStream,40) 'DIB Header Size (4 bytes) - 40 bytes
80+
WriteInt(dataStream,bmpWidth) 'Bitmap Width (4 bytes)
81+
WriteInt(dataStream,bmpHeight) 'Bitmap Height (4 bytes)
82+
WriteShort(dataStream,1) 'Color Planes (2 bytes) - Must be 1
83+
WriteShort(dataStream,8) 'Color Depth (2 bytes) - Bits Per Pixel
84+
WriteInt(dataStream,0) 'Compression Method (4 bytes) - 0 equals BI_RGB (no compression), 1 equals BI_RLE8 (lossless run-length encoding)
85+
WriteInt(dataStream,bmpSizeTotalM4) 'Size of the raw bitmap data (4 bytes) - 0 can be given for BI_RGB bitmaps
86+
WriteInt(dataStream,2835) 'Horizontal resolution of the image (4 bytes) - Pixels Per Metre (2835 PPM equals 72.009 DPI/PPI)
87+
WriteInt(dataStream,2835) 'Vertical resolution of the image (4 bytes) - Pixels Per Metre (2835 PPM equals 72.009 DPI/PPI)
88+
WriteInt(dataStream,256) 'Number of colors in the color palette (4 bytes)
89+
WriteInt(dataStream,0) 'Number of important colors (4 bytes) - 0 when every color is important
90+
'Print("wrote dib")
91+
92+
'------ Color Table
93+
For paletteIndex = 0 To 255
94+
WriteByte(dataStream,PalB[paletteIndex]) 'Blue (4 bytes) - offset 54
95+
WriteByte(dataStream,PalG[paletteIndex]) 'Green (4 bytes) - offset 58
96+
WriteByte(dataStream,PalR[paletteIndex]) 'Red (4 bytes) - offset 62
97+
WriteByte(dataStream,0) 'Alpha (4 bytes) - offset 66
98+
If paletteIndex = 255 Then
99+
'Print("wrote color table")
100+
EndIf
101+
Next
102+
103+
'------ Pixel Array
104+
Local px:Int, py:Int
105+
Local R:Int, G:Int, B:Int, ARGB:Long
106+
Local bestDistance:Int, bestIndex:Int, distance:Int
107+
Local RDIFF:Int, GDIFF:Int, BDIFF:Int
108+
109+
For py = bmpHeight -1 To 0 Step -1
110+
For px = 0 To bmpWidthM4 -1
111+
If px < bmpWidth 'if a valid pixel on canvas
112+
bestDistance = 17000000
113+
bestIndex = 0
114+
distance = 0
115+
116+
For paletteIndex = 0 To 255 ' Check all color indexes for best match by pythagora
117+
ARGB = ReadPixel(image,px,py)
118+
R = (ARGB & $00FF0000) Shr 16
119+
G = (ARGB & $FF00) Shr 8
120+
B = (ARGB & $FF)
121+
RDIFF = Abs(R - palR[paletteIndex])
122+
GDIFF = Abs(G - palG[paletteIndex])
123+
BDIFF = Abs(B - palB[paletteIndex])
124+
distance = (RDIFF^2 + GDIFF^2 + BDIFF^2)
125+
If distance <= bestDistance Then
126+
bestIndex = paletteIndex
127+
bestDistance = distance
128+
EndIf
129+
'Print("working" + paletteIndex)
130+
Next
131+
WriteByte(dataStream,bestIndex)
132+
Else
133+
WriteByte(dataStream,0) ' line padding
134+
EndIf
135+
Next
136+
Next
137+
For paletteIndex = 1 To bmpSizeTotalM4 - bmpSizeTotal ' eof padding
138+
WriteByte(dataStream,0)
139+
Next
140+
141+
CloseStream(dataStream)
142+
'Print ("stream closed")
143+
EndFunction
144+
43145
EndType
44146

45147
Rem
@@ -101,7 +203,8 @@ Type TAppFileIO
101203
Notify("Cannot overwrite source image!",True)
102204
ElseIf exportedFile <> importedFile Then
103205
'Writing new file
104-
SavePixmapPNG(tempOutputImage,exportedFile)
206+
'SavePixmapPNG(tempOutputImage,exportedFile)
207+
TBitmapIndex.FPixmapToIndexedBitmap(tempOutputImage,exportedFile+".bmp")
105208
FRevertPrep()
106209
Else
107210
'On Cancel
@@ -281,6 +384,7 @@ Type TAppOutput
281384
SetRotation(0)
282385
'Output copy for saving
283386
TAppFileIO.tempOutputImage = GrabPixmap(0,96,768,384)
387+
'ConvertPixmap(TAppFileIO.tempOutputImage,PF_BGR888)
284388
Flip(1)
285389
If TAppFileIO.prepForSave
286390
TAppFileIO.FPrepForSave()

0 commit comments

Comments
 (0)