source: trunk/Packages/bgrabitmap/bgrareadbmpmiomap.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 6.5 KB
Line 
1unit BGRAReadBmpMioMap;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, FPimage, BGRABitmapTypes;
9
10const
11 MioMapMagicValue = 'RL';
12 MioMapTransparentColor = $F81F;
13
14type
15 TMioHeader = packed record
16 magic: packed array[1..2] of char;
17 format: word;
18 width,height,nbColors,nbChunks: word;
19 end;
20
21 TPixelArray = array of TBGRAPixel;
22
23 { TBGRAReaderBmpMioMap }
24
25 TBGRAReaderBmpMioMap = class(TFPCustomImageReader)
26 private
27 function ReadHeader(Stream: TStream; out header: TMioHeader): boolean;
28 function ReadPalette(Stream: TStream; nbColors: integer; alphaChannel: boolean): TPixelArray;
29 procedure UncompressChunks(Stream: TStream; nbChunks: integer; palette: TPixelArray; img: TFPCustomImage);
30 public
31 procedure InternalRead (Stream:TStream; Img:TFPCustomImage); override;
32 function InternalCheck (Stream:TStream) : boolean; override;
33 end;
34
35function MioMapToBGRA(AColor: Word): TBGRAPixel;
36function BGRAToMioMap(const AColor: TBGRAPixel): Word;
37function MioMapToAlpha(AValue: Byte): Byte;
38function AlphaToMioMap(AValue: Byte): Byte;
39
40implementation
41
42uses bufstream;
43
44function MioMapToBGRA(AColor: Word): TBGRAPixel;
45begin
46 if AColor = MioMapTransparentColor then
47 result := BGRAPixelTransparent
48 else
49 result := Color16BitToBGRA(AColor);
50end;
51
52function BGRAToMioMap(const AColor: TBGRAPixel): Word;
53begin
54 if AColor.alpha < 7 then
55 result := MioMapTransparentColor
56 else
57 begin
58 result := BGRAToColor16Bit(AColor);
59 if result = MioMapTransparentColor then dec(result);
60 end;
61end;
62
63function MioMapToAlpha(AValue: Byte): Byte;
64begin
65 result := AValue*255 div 32;
66end;
67
68function AlphaToMioMap(AValue: Byte): Byte;
69begin
70 result := (AValue*32 + 64) div 255;
71end;
72
73{ TBGRAReaderBmpMioMap }
74
75function TBGRAReaderBmpMioMap.ReadHeader(Stream: TStream; out header: TMioHeader
76 ): boolean;
77begin
78 result := false;
79 fillchar({%H-}header,sizeof(header),0);
80 if stream.Read(header, sizeof(header))<> sizeof(header) then exit;
81 if header.magic <> MioMapMagicValue then exit;
82 header.format:= LEtoN(header.format);
83 header.width:= LEtoN(header.width);
84 header.height:= LEtoN(header.height);
85 header.nbColors:= LEtoN(header.nbColors);
86 header.nbChunks:= LEtoN(header.nbChunks);
87 if header.format > 1 then exit;
88 result := true;
89end;
90
91function TBGRAReaderBmpMioMap.ReadPalette(Stream: TStream; nbColors: integer;
92 alphaChannel: boolean): TPixelArray;
93var mioPalette: packed array of word;
94 nbColorsRead,i: integer;
95 colorValue: word;
96 alphaPalette: packed array of byte;
97begin
98 setlength(mioPalette, nbColors);
99 setlength(result,nbColors);
100 nbColorsRead:= Stream.Read({%H-}mioPalette[0], nbColors*2) div 2;
101 for i := 0 to nbColorsRead-1 do
102 begin
103 colorValue := LEtoN(mioPalette[i]);
104 result[i] := MioMapToBGRA(colorValue);
105 end;
106 for i := nbColorsRead to nbColors-1 do
107 result[i] := BGRAPixelTransparent;
108 if alphaChannel then
109 begin
110 setlength(alphaPalette,nbColors);
111 Stream.Read(alphaPalette[0],nbColors);
112 for i := 0 to nbColors-1 do
113 if mioPalette[i] <> MioMapTransparentColor then
114 result[i].alpha := MioMapToAlpha(alphaPalette[i]);
115 end;
116end;
117
118procedure TBGRAReaderBmpMioMap.UncompressChunks(Stream: TStream; nbChunks: integer;
119 palette: TPixelArray; img: TFPCustomImage);
120var i,maxChunkSize: integer;
121 chunkSizes: array of integer;
122 chunkData: packed array of byte;
123 pos,bytesRead: integer;
124 palLen: integer;
125 x,y: integer;
126 p: PBGRAPixel;
127 colorOffset: integer;
128 b: byte;
129 w,h: integer;
130
131 procedure UncompressPixel(colorNumber, repeatCount: integer);
132 var
133 c: TBGRAPixel;
134 begin
135 if colorNumber >= palLen then
136 c := BGRAPixelTransparent
137 else
138 c := palette[colorNumber];
139 while (repeatCount > 0) and (y < h) do
140 begin
141 if p <> nil then
142 begin
143 p^ := c;
144 inc(p);
145 end else
146 img.Colors[x,y] := BGRAToFPColor(c);
147 inc(x);
148 if x = w then
149 begin
150 x := 0;
151 inc(y);
152 if p <> nil then
153 begin
154 if y >= h then p := nil
155 else
156 p := TBGRACustomBitmap(Img).ScanLine[y];
157 end;
158 end;
159 dec(repeatCount);
160 end;
161 end;
162
163begin
164 palLen := length(palette);
165 if (img.Width = 0) or (img.Height = 0) or (palLen = 0) then exit;
166
167 maxChunkSize := 1;
168 setlength(chunkSizes, nbChunks);
169 for i := 0 to nbChunks-1 do
170 begin
171 if stream.read({%H-}b,1)=0 then b := 0;
172 if b < 255 then
173 begin
174 chunkSizes[i] := b;
175 end else
176 begin
177 if stream.read(b,1)=0 then b := 0;
178 chunkSizes[i] := b shl 8;
179 if stream.read(b,1)=0 then b := 0;
180 chunkSizes[i] += b;
181 end;
182 if chunkSizes[i]>maxChunkSize then
183 maxChunkSize := chunkSizes[i];
184 end;
185
186 setlength(chunkData, maxChunkSize);
187 x := 0;
188 y := 0;
189 w := img.Width;
190 h := img.Height;
191 colorOffset:= 0;
192 if Img is TBGRACustomBitmap then
193 begin
194 p := TBGRACustomBitmap(Img).ScanLine[y];
195 TBGRACustomBitmap(Img).FillTransparent;
196 end
197 else
198 p := nil;
199 for i:= 0 to nbChunks-1 do
200 begin
201 bytesRead := Stream.Read(chunkData[0], chunkSizes[i]);
202 pos := 0;
203 while pos < bytesRead do
204 begin
205 if (chunkData[pos] = $FE) and (pos+2 < bytesRead) then
206 begin
207 UncompressPixel(chunkData[pos+1]+colorOffset,chunkData[pos+2]);
208 inc(pos,3);
209 end else
210 if (chunkData[pos] = $ff) and (pos+1 < bytesRead) then
211 begin
212 UncompressPixel(0,chunkData[pos+1]);
213 inc(pos,2);
214 end else
215 if (chunkData[pos] = $fd) and (pos+2 < bytesRead) then
216 begin
217 colorOffset:= chunkData[pos+1] + (chunkData[pos+2] shl 8);
218 inc(pos,3);
219 end else
220 if chunkData[pos] = 0 then
221 begin
222 UncompressPixel(0,1);
223 inc(pos);
224 end else
225 begin
226 UncompressPixel(chunkData[pos]+colorOffset,1);
227 inc(pos);
228 end;
229 end;
230 end;
231end;
232
233procedure TBGRAReaderBmpMioMap.InternalRead(Stream: TStream; Img: TFPCustomImage);
234var header: TMioHeader;
235 palette: TPixelArray;
236 buf: TReadBufStream;
237begin
238 if not ReadHeader(stream, header) then exit;
239 buf := TReadBufStream.Create(Stream,1024);
240 Img.SetSize(header.width,header.height);
241 palette := ReadPalette(stream, header.nbColors, header.format = 1);
242 UncompressChunks(stream,header.nbChunks, palette, Img);
243 buf.Free;
244end;
245
246function TBGRAReaderBmpMioMap.InternalCheck(Stream: TStream): boolean;
247var OldPosition : int64;
248 dummy: TMioHeader;
249begin
250 OldPosition:= stream.Position;
251 result := ReadHeader(stream, dummy);
252 stream.Position:= OldPosition;
253end;
254
255initialization
256
257 DefaultBGRAImageReader[ifBmpMioMap] := TBGRAReaderBmpMioMap;
258
259end.
Note: See TracBrowser for help on using the repository browser.