1 {
2 Vampyre Imaging Library
3 by Marek Mauder
4 http://imaginglib.sourceforge.net
6 The contents of this file are used with permission, subject to the Mozilla
7 Public License Version 1.1 (the "License"); you may not use this file except
8 in compliance with the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/MPL-1.1.html
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
13 the specific language governing rights and limitations under the License.
15 Alternatively, the contents of this file may be used under the terms of the
16 GNU Lesser General Public License (the "LGPL License"), in which case the
17 provisions of the LGPL License are applicable instead of those above.
18 If you wish to allow use of your version of this file only under the terms
19 of the LGPL License and not to allow others to use your version of this file
20 under the MPL, indicate your decision by deleting the provisions above and
21 replace them with the notice and other provisions required by the LGPL
22 License. If you do not delete the provisions above, a recipient may use
23 your version of this file under either the MPL or the LGPL License.
25 For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
26 }
28 {
29 This unit contains image format loader/saver for Windows Bitmap images.
30 }
33 {$I ImagingOptions.inc}
35 interface
37 uses
40 type
41 { Class for loading and saving Windows Bitmap images.
42 It can load/save 8bit indexed, 16, 24, 32 bit RGB or ARGB
43 images with or without RLE compression. It can also load 1/4 bit
44 indexed images and OS2 bitmaps.}
46 protected
55 public
57 published
58 { Controls that RLE compression is used during saving. Accessible trough
59 ImagingBitmapRLE option.}
63 implementation
65 const
72 const
73 { Bitmap file identifier 'BM'.}
76 { Constants for the TBitmapInfoHeader.Compression field.}
85 type
86 { File Header for Windows/OS2 bitmap file.}
95 { Info Header for Windows bitmap file version 4.}
119 { Info Header for OS2 bitmaps.}
128 { Used in RLE encoding and decoding.}
135 { TBitmapFileFormat class implementation }
138 begin
152 var
163 var
166 begin
168 begin
169 // If BI.Height is < 0 then image data are stored non-flipped
170 // but default in windows is flipped so if Height is positive we must
171 // flip it
174 begin
175 // For 1 and 4 bit images load aligned data, they will be converted to
176 // 8 bit and unaligned later
181 else
184 end
185 else
186 begin
187 // Images with pixels of size >= 1 Byte are read line by line and
188 // copied to image bits without padding bytes
190 try
193 begin
196 end
197 else
199 begin
203 finally
211 var
219 begin
223 try
230 // Row in dest image where actuall writting will be done
233 begin
234 // Read RLE op-code
238 begin
239 // A byte Count of zero means that this is a special
240 // instruction.
243 begin
244 // Move to next row
251 begin
252 // Move to a new relative position
258 end
259 else
260 // Do not read data after EOF
263 // Take padding bytes and nibbles into account
266 // Store absolute data. Command code is the
267 // number of absolute bytes to store
269 begin
271 begin
276 end
277 else
281 // Odd number of bytes is followed by a pad byte
285 end
286 else
287 begin
288 // Take padding bytes and nibbles into account
291 // Store a run of the same color value
293 begin
296 else
302 finally
308 var
316 begin
320 try
326 // Row in dest image where actuall writting will be done
329 begin
330 // Read RLE op-code
334 begin
335 // A byte Count of zero means that this is a special
336 // instruction.
339 begin
340 // Move to next row
347 begin
348 // Move to a new relative position
354 end
355 else
357 // Do not read data after EOF
360 // Take padding bytes into account
363 // Store absolute data. Command code is the
364 // number of absolute bytes to store
368 // Odd number of bytes is followed by a pad byte
372 end
373 else
374 begin
375 // Take padding bytes into account
378 // Store a run of the same color value. Count is number of bytes to store
383 finally
388 begin
392 try
399 // Bitmap Info reading
401 begin
402 // OS/2 type bitmap, reads info header without 4 already read bytes
406 begin
413 end
414 else
415 begin
416 // Windows type bitmap
417 HeaderSize := Min(BI.Size - SizeOf(BI.Size), SizeOf(BI) - SizeOf(BI.Size)); // do not read more than size of BI!
419 // SizeImage can be 0 for BI_RGB images, but it is here because of:
420 // I saved 8bit bitmap in Paint Shop Pro 8 as OS2 RLE compressed.
421 // It wrote strange 64 Byte Info header with SizeImage set to 0
422 // Some progs were able to open it, some were not.
426 // Bit mask reading. Only read it if there is V3 header, V4 header has
427 // masks laoded already (only masks for RGB in V3).
435 // Set XRGB4 or ARGB4 according to value of alpha mask
438 Format := ifR5G6B5
439 else
440 // R5G5B5 is default 16bit format (with Compression = BI_RGB or masks).
441 // We set it to A1.. and later there is a check if there are any alpha values
442 // and if not it is changed to X1R5G5B5
454 // Palette settings and reading
456 begin
457 // Seek to the begining of palette
459 smFromBeginning);
461 begin
462 // OS/2 type
465 try
469 begin
474 finally
477 end
478 else
479 begin
480 // Windows type
490 // Seek to the beginning of image bits
501 begin
502 // Alpha mask is not stored in file (V3) or not defined.
503 // Check alpha channels of loaded images if they might contain them.
505 begin
506 // Check if there is alpha channel present in A1R5GB5 images, if it is not
507 // change format to X1R5G5B5
510 end
512 begin
513 // Check if there is alpha channel present in A8R8G8B8 images, if it is not
514 // change format to X8R8G8B8
521 begin
522 // 1 and 4 bpp images are supported only for loading which is now
523 // so we now convert them to 8bpp (and unalign scanlines).
527 begin
528 // RLE4 bitmaps are translated to 8bit during RLE decoding
533 // Enlarge palette
538 finally
545 var
554 const
556 var
564 begin
566 begin
567 // Flush buffer if necessary
575 begin
578 begin
580 begin
586 begin
589 // Determine run length
591 begin
592 // If we reach max run length or byte with different value
593 // we end this run
595 Break;
600 begin
601 // If there are not some bytes with the same value we
602 // compute how many different bytes are there
604 begin
605 // Stop diff byte counting if there two bytes with the same value
606 // or DiffCount is too big
609 Break;
614 // Now store absolute data (direct copy image->file) or
615 // store RLE code only (number of repeats + byte to be repeated)
617 begin
618 // Save 'Absolute Data' (0 + number of bytes) but only
619 // if number is >2 because (0+1) and (0+2) are other special commands
622 // Write absolute data to buffer
627 // Odd number of bytes must be padded
630 end
631 else
632 begin
633 // Save number of repeats and byte that should be repeated
640 // Save 'End Of Line' command
644 // Save 'End Of Bitmap' command
647 // Flush buffer
652 begin
656 try
661 // Other fields will be filled later - we don't know all values now
665 // Save images with alpha in V4 format
667 else
668 // Save images without alpha in V3 format - for better compatibility
676 // Set compression
680 ((BI.BitCount = 16) and (Format <> ifX1R5G5B5))) and (Info.BytesPerPixel = 2){V4 temp hack} then
682 else
684 // Write header (first time)
687 // Write mask info
689 begin
692 begin
697 end
698 else
699 begin
700 // Set masks for A8R8G8B8
706 // If V3 header is used RGB masks must be written to file separately.
707 // V4 header has embedded masks (V4 is default for formats with alpha).
711 // Write palette
718 begin
719 // Save uncompressed data, scanlines must be filled with pad bytes
720 // to be multiples of 4, save as bottom-up (Windows native) bitmap
726 begin
731 end
732 else
733 begin
734 // Save data with RLE8 compression
735 SaveRLE8;
740 // Rewrite header with new values
748 finally
756 var
758 begin
760 // Convert FP image to RGB/ARGB according to presence of alpha channel
763 // Convert all grayscale and indexed images to Index8 unless they have alpha
764 // (preserve it)
767 // Convert images with alpha channel to A8R8G8B8
768 ConvFormat := ifA8R8G8B8
770 // Convert 16bit RGB images (no alpha) to X1R5G5B5
771 ConvFormat := ifX1R5G5B5
772 else
773 // Convert all other formats to R8G8B8
780 var
783 begin
787 begin
794 initialization
797 {
798 File Notes:
800 -- TODOS ----------------------------------------------------
801 - nothing now
802 - Add option to choose to save V3 or V4 headers.
804 -- 0.25.0 Changes/Bug Fixes ---------------------------------
805 - Fixed problem with indexed BMP loading - some pal entries
806 could end up with alpha=0.
808 -- 0.23 Changes/Bug Fixes -----------------------------------
809 - Now saves bitmaps as bottom-up for better compatibility
810 (mainly Lazarus' TImage!).
811 - Fixed crash when loading bitmaps with headers larger than V4.
812 - Temp hacks to disable V4 headers for 32bit images (compatibility with
813 other soft).
815 -- 0.21 Changes/Bug Fixes -----------------------------------
816 - Removed temporary data allocation for image with aligned scanlines.
817 They are now directly written to output so memory requirements are
818 much lower now.
819 - Now uses and recognizes BITMAPINFOHEADERV4 when loading/saving.
820 Mainly for formats with alpha channels.
821 - Added ifR5G6B5 to supported formats, changed converting to supported
822 formats little bit.
823 - Rewritten SaveRLE8 nested procedure. Old code was long and
824 mysterious - new is short and much more readable.
825 - MakeCompatible method moved to base class, put ConvertToSupported here.
826 GetSupportedFormats removed, it is now set in constructor.
827 - Rewritten LoadRLE4 and LoadRLE8 nested procedures.
828 Should be less buggy an more readable (load inspired by Colosseum Builders' code).
829 - Made public properties for options registered to SetOption/GetOption
830 functions.
831 - Addded alpha check to 32b bitmap loading too (teh same as in 16b
832 bitmap loading).
833 - Moved Convert1To8 and Convert4To8 to ImagingFormats
834 - Changed extensions to filename masks.
835 - Changed SaveData, LoadData, and MakeCompatible methods according
836 to changes in base class in Imaging unit.
838 -- 0.19 Changes/Bug Fixes -----------------------------------
839 - fixed wrong const that caused A4R4G4B4 BMPs to load as A1R5G5B5
840 - fixed the bug that caused 8bit RLE compressed bitmaps to load as
841 whole black
843 -- 0.17 Changes/Bug Fixes -----------------------------------
844 - 16 bit images are usually without alpha but some has alpha
845 channel and there is no indication of it - so I have added
846 a check: if all pixels of image are with alpha = 0 image is treated
847 as X1R5G5B5 otherwise as A1R5G5B5
849 -- 0.13 Changes/Bug Fixes -----------------------------------
850 - when loading 1/4 bit images with dword aligned dimensions
851 there was ugly memory rewritting bug causing image corruption
853 }