source: branches/2.19_branch/NewView/HelpBitmap.pas@ 292

Last change on this file since 292 was 32, checked in by RBRi, 19 years ago

% more source cleanup (uses)

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1Unit HelpBitmap;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2003 Aaron Lawrence (aaronl at consultant dot com)
5// This software is released under the Gnu Public License - see readme.txt
6
7Interface
8
9// Encapsulates a bitmap as stored in a IPF file.
10// Once created from file data they can be used as a normal bitmap.
11
12uses
13 BseDos,
14 OS2Def,
15 PMBitmap,
16 Classes,
17 Graphics,
18 SysUtils,
19 IPFFileFormatUnit;
20
21type
22 EHelpBitmapException = class( Exception )
23 end;
24
25 // Lead part of BITMAPARRAYFILEHEADER
26 INFBITMAPARRAYHEADER = record
27 usType: USHORT; // 'BA', 16706
28 cbSize: ULONG; // Size of the BITMAPARRAYFILEHEADER structure in bytes.
29 offNext: ULONG; // Offset of the next BITMAPARRAYFILEHEADER structure from the start of the file.
30 cxDisplay: USHORT; // Device width, in pels.
31 cyDisplay: USHORT; // Device height, in pels.
32 end;
33
34 INFBITMAPHEADER = record
35 // BITMAP FILE HEADER
36 usType: USHORT; // = 'bM'
37 cbSize: ULONG;
38 xHotspot: USHORT;
39 yHotspot: USHORT;
40 offBits: ULONG; // =size(hdr)+size(palette)
41 // BITMAP INFO HEADER
42 cbFIx: ULONG; // =size(info_hdr) (usually = 12?)
43 cx: USHORT; // x size
44 cy: USHORT; // y size
45 cPlanes: USHORT; // planes, =1
46 cBitCount: USHORT;
47 end;
48
49 THelpBitmap = class( TBitmap )
50 protected
51 _Header: INFBITMAPHEADER;
52 _PaletteColorCount: longint;
53 _pPalette: ^RGB;
54 _BitsSize: longint;
55 _FileHandle: HFile;
56
57 _UncompressedBlockSize: longint;
58
59 function GetPaletteSize: longint;
60 procedure ReadBitmapData( Blocks: TList;
61 TotalSize: longint );
62 public
63 constructor CreateFromHelpFile( FileHandle: HFile;
64 Offset: longint );
65 destructor Destroy; override;
66 end;
67
68var
69 LZWDecompressBlock: function( pInput: PBYTE;
70 pOutput: PBYTE;
71 bytesIn: ULONG;
72 Var bytesOut: ULONG;
73 Var FinalCode: byte ): BOOL;
74 APIENTRY;
75// 'newview' index 1;
76
77Implementation
78
79uses
80 ACLFileIOUtility, ACLUtility,
81 ACLDialogs;
82
83const
84 BFT_bMAP =$4d62; // 'bM'
85 BFT_BITMAP_ARRAY = $4142; // 'BA'
86
87type
88 INFBITMAPDATAHEADER = record
89 ulTotalSize: ULONG;
90 usUncompressedBlockSize: USHORT; // bytes per block, after decompression
91 end;
92
93 TBitmapBlock = class
94 _Data: PBYTE;
95 _Size: USHORT;
96 _CompressionType: uint8;
97 destructor Destroy; override;
98 end;
99
100destructor TBitmapBlock.Destroy;
101begin
102 DeallocateMemory( _Data );
103 inherited Destroy;
104end;
105
106constructor THelpBitmap.CreateFromHelpFile( FileHandle: HFILE;
107 Offset: longint );
108var
109 WordsPerLine: longint;
110 LineSize: longint;
111 DataHeader: INFBITMAPDATAHEADER;
112 BytesRead: longint;
113
114 Block: TBitmapBlock;
115 Blocks: TList;
116 BlockIndex: longint;
117 ImageType: USHORT;
118 BitmapArrayHeader: INFBITMAPARRAYHEADER;
119begin
120 MySeek( FileHandle, Offset );
121 MyRead( FileHandle, Addr( ImageType ), sizeof( ImageType ) );
122
123 if ImageType = BFT_BITMAP_ARRAY then
124 begin
125 // skip array header and read first bitmap only
126 MySkip( FileHandle, Sizeof( BitmapArrayHeader ) - sizeof( ImageType ) );
127 end
128 else
129 begin
130 // skip back over imagetype bytes to read header.
131 MySkip( FileHandle, - sizeof( ImageType ) );
132 end;
133
134 // Read bitmap header
135 MyRead( FileHandle, Addr( _Header ), sizeof( _Header ) );
136
137 // Check it's got a valid type
138 if _Header.usType <> BFT_bMAP then
139 raise EHelpBitmapException.Create( 'Invalid bitmap header' );
140
141 _Header.usType := $4d42; // sibyl only accepts 'BM' not 'bM'
142
143 // We can only parse bitmaps with 1 colour plane
144 // (I can't be bothered and have never seen bitmaps
145 // with more than 1 color plane)
146 if _Header.cPlanes <> 1 then
147 exit;
148
149 _PaletteColorCount := 0;
150 if _Header.cBitCount < 24 then
151 _PaletteColorCount := 1 shl _Header.cBitCount;
152
153 // OS/2 always rounds bitmap rows up to a word:
154 WordsPerLine := ( _Header.cBitCount * _Header.cx + 31 ) div 32;
155 LineSize := WordsPerLine * 4;
156
157 // Total size of the bitmap pixel data
158 _BitsSize := LineSize * _Header.cy;
159
160 // Correct header offset - it is wrong in the header (why?)
161 _Header.OffBits := sizeof( _Header ) + GetPaletteSize;
162
163 // Load palette
164 _pPalette := AllocateMemory( GetPaletteSize );
165 MyRead( FileHandle, _pPalette, GetPaletteSize );
166
167 // Read data header
168 MyRead( FileHandle, Addr( DataHeader ), sizeof( DataHeader ) );
169 _UncompressedBlockSize := DataHeader.usUncompressedBlockSize;
170
171 // For counting total size, we have already read some bytes:
172 // the uncompressedblocksize field
173 BytesRead := sizeof( DataHeader.usUncompressedBlockSize );
174 Blocks := TList.Create;
175
176 while BytesRead < DataHeader.ulTotalSize do
177 begin
178 Block := TBitmapBlock.Create;
179
180 // Read the block size
181 MyRead( FileHandle, Addr( Block._Size ), sizeof( Block._Size ) );
182 inc( BytesRead, sizeof( Block._Size ) );
183
184 // Read the compression type
185 MyRead( FileHandle, Addr( Block._CompressionType ), sizeof( Block._CompressionType ) );
186 inc( BytesRead, sizeof( Block._CompressionType ) );
187
188 // since size in the file includes this compression type field, subtract it
189 dec( Block._Size, sizeof( Block._CompressionType ) );
190
191 // Now read the block
192 Block._Data := AllocateMemory( Block._Size );
193 MyRead( FileHandle, Block._Data, Block._Size );
194
195 inc( BytesRead, Block._Size );
196
197 Blocks.Add( Block );
198
199 end;
200 ReadBitmapData( Blocks, sizeof( _Header ) + GetPaletteSize + _BitsSize );
201
202 for BlockIndex := 0 to Blocks.Count - 1 do
203 begin
204 Block := Blocks[ BlockIndex ];
205 Block.Destroy;
206 end;
207
208 Blocks.Destroy;
209end;
210
211function THelpBitmap.GetPaletteSize: longint;
212begin
213 Result := sizeof( RGB ) * _PaletteColorCount;
214end;
215
216destructor THelpBitmap.Destroy;
217begin
218 DeallocateMemory( _pPalette );
219 inherited Destroy;
220end;
221
222procedure THelpBitmap.ReadBitmapData( Blocks: TList;
223 TotalSize: longint );
224var
225 BytesWritten: longint;
226 BytesWrittenFromBlock: longword;
227 BytesRemainingInBlock: longword;
228 BytesRemainingInBitmap: longword;
229 FillerBytesRequired: longint;
230 lastOutByte: byte;
231 BitmapOutputPointer: PByte;
232 Block: TBitmapBlock;
233 BlockIndex: longint;
234 BitmapData: PBYTE;
235begin
236 // Allocate memory to store the bitmap
237 GetMem( BitmapData, TotalSize );
238
239 // Copy header to bitmap
240 MemCopy( Addr( _Header ),
241 BitmapData,
242 sizeof( _Header ) );
243
244 // Copy palette into bitmap
245 MemCopy( _pPalette,
246 BitmapData + sizeof( _Header ),
247 GetPaletteSize );
248
249 BytesWritten := 0;
250
251 // Point to start writing to bitmap bits.
252 BitmapOutputPointer := BitmapData + sizeof( _Header ) + GetPaletteSize;
253
254 for BlockIndex := 0 to Blocks.Count - 1 do
255 begin
256 Block := Blocks[ BlockIndex ];
257
258 case Block._CompressionType of
259 0,1: // uncompressed (I'm not sure about 1)
260 begin
261 MemCopy( Block._Data,
262 BitmapOutputPointer,
263 Block._Size );
264 BytesWrittenFromBlock := Block._Size;
265 inc( BytesWritten, BytesWrittenFromBlock );
266 end;
267
268 2: // LZW compression
269 begin
270 // decompress block
271 if not Assigned( LZWDecompressBlock )then
272 raise EHelpBitmapException.Create( 'Cannot decode bitmap - DLL not found' );
273
274 LZWDecompressBlock( Block._Data,
275 BitmapOutputPointer,
276 Block._Size,
277 BytesWrittenFromBlock,
278 lastOutByte );
279
280 inc( BytesWritten, BytesWrittenFromBlock );
281
282 // If the uncompressed data stopped short then
283 // copy the final code (byte) into remaining bytes
284 if ( BytesWrittenFromBlock < _UncompressedBlockSize )
285 and ( BytesWritten < _BitsSize ) then
286 begin
287 BytesRemainingInBlock := _UncompressedBlockSize - BytesWrittenFromBlock;
288 BytesRemainingInBitmap := _BitsSize - BytesWritten;
289
290 FillerBytesRequired := Min( BytesRemainingInBlock,
291 BytesRemainingInBitmap );
292
293 FillMem( BitmapOutputPointer + BytesWrittenFromBlock,
294 FillerBytesRequired,
295 LastOutByte );
296 inc( BytesWritten, FillerBytesRequired );
297 inc( BytesWrittenFromBlock, FillerBytesRequired );
298 end;
299 end;
300 else
301 raise EHelpBitmapException.Create( 'Unrecognised bitmap block type' );
302 end; // case
303
304 assert( BytesWrittenFromBlock <= _UncompressedBlockSize );
305 assert( BytesWritten <= _BitsSize );
306
307 if ( BitmapOutputPointer + BytesWrittenFromBlock
308 > BitmapData + TotalSize ) then
309 assert( false );
310
311 inc( BitmapOutputPointer, BytesWrittenFromBlock );
312 end;
313
314 LoadFromMem( BitmapData^, TotalSize );
315 FreeMem( BitmapData, TotalSize );
316end;
317
318Initialization
319End.
Note: See TracBrowser for help on using the repository browser.