|
Class: WindowsIconReader
Object
|
+--ImageReader
|
+--WindowsIconReader
- Package:
- stx:libview2
- Category:
- Graphics-Images-Readers
- Version:
- rev:
1.107
date: 2023/08/08 08:44:22
- user: cg
- file: WindowsIconReader.st directory: libview2
- module: stx stc-classLibrary: libview2
this class provides methods for loading Windows and OS2 icon and bmp files.
The class name *IconReader is a bad, historic choice - it was originally
written to read icons only, but evolved over time and is now also
capable of reading/writing bmp and cursor files.
The reader should support allmost all formats: Win2, Win3, Win4, Win5, WINCE and OS2.
(incl. PNG and JPG compression, and WINCE depth2 images)
Image writing is only supported for BMP format with depth 1,4,8 and 24 bit images.
The reader tries to figure out which version of BMP/ICO is used.
It seems to be able to load most formats, but who knows ...
[notice:]
when reading an ICO/CUR file with multiple icons in it,
the first image is returned as such, holding on the other images via its
imageFrames instvar.
Thus, the imageEditor will usually present the first of the images,
and offer a next-in-sequence button to step through them.
To get a collection of all images, collect the images from the sequence, as in:
someIcoImage imageFrames collect:#image
copyrightCOPYRIGHT (c) 1993 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
fileFormatDescriptionInformation from http://www.daubnet.com/formats/BMP.html - no Warranty.
Name Size Offset Description
Header 14 bytes Windows Structure: BITMAPFILEHEADER
Signature 2 bytes 0 'BM'
FileSize 4 bytes 2 File size in bytes
reserved 4 bytes 6 unused (=0)
DataOffset 4 bytes 10 File offset to Raster Data
InfoHeader 40 bytes Windows Structure: BITMAPINFOHEADER
different sizes, depending on Windows-version:
12 - Win2.x or OS/2 1.x
40 - WinNT, Win3.x or later
52 - adds undocumented; adds r/g/b masks
56 - adds undocumented; adds r/g/b/a masks
64 - OS/2 2.x
108 - WinNT4.0, 95 or later
124 - WinNT5.0, 98 or later
Size 4 bytes 14 Size of InfoHeader =40
Width 4 bytes 18 Bitmap Width
Height 4 bytes 22 Bitmap Height
Planes 2 bytes 26 Number of Planes (=1)
BitCount 2 bytes 28 Bits per Pixel
1 = monochrome palette. NumColors = 1
4 = 4bit palletized. NumColors = 16
8 = 8bit palletized. NumColors = 256
16 = 16bit RGB. NumColors = 65536 (?)
24 = 24bit RGB. NumColors = 16M
Compression 4 bytes 30 Type of Compression
0 = RGB no compression
1 = RLE8 8bit RLE encoding
2 = RLE4 4bit RLE encoding
3 = BITFIELDS Windows V3+ only
4 = JPEG Windows V3+ only
5 = PNG Windows V3+ only
6 = ALPHA_BITFIELDS Windows CE only
3 = HUFFMAN1D OS/2 2.x-only
4 = RLE24 OS/2 2.x-only
ImageSize 4 bytes 34 (compressed) Size of Image
It is valid to set this =0 if Compression = 0
XpixelsPerM 4 bytes 38 horizontal resolution: Pixels/meter
YpixelsPerM 4 bytes 42 vertical resolution: Pixels/meter
ColorsUsed 4 bytes 46 Number of actually used colors
ColorsImportant
4 bytes 50 Number of important colors
0 = all
ColorTable 4 * NumColors bytes (3 on Win2)
present only if Info.BitsPerPixel <= 8
colors should be ordered by importance
Red 1 byte Red intensity
Green 1 byte Green intensity
Blue 1 byte Blue intensity
reserved 1 byte unused (=0)
repeated NumColors times
Raster Data Info.ImageSize bytes The pixel data
Raster Data encoding:
Depending on the image's BitCount and on the Compression flag there are 6 different encoding schemes.
All of them share the following:
Pixels are stored bottom-up, left-to-right. Pixel lines are padded with zeros to end on a 32bit (4byte) boundary. For
uncompressed formats every line will have the same number of bytes. Color indices are zero based, meaning a pixel
color of 0 represents the first color table entry, a pixel color of 255 (if there are that many) represents the 256th entry.
For images with more than 256 colors there is no color table.
Raster Data encoding for 1bit / black & white images:
BitCount = 1 Compression = 0
Every byte holds 8 pixels, its highest order bit representing the leftmost pixel of those. There are 2 color table entries.
Some readers will ignore them though, and assume that 0 is black and 1 is white. If you are storing black and white
pictures you should stick to this, with any other 2 colors this is not an issue. Remember padding with zeros up to a
32bit boundary (This can be up to 31 zeros/pixels!)
Raster Data encoding for 4bit / 16 color images:
BitCount = 4 Compression = 0
Every byte holds 2 pixels, its high order 4 bits representing the left of those. There are 16 color table entries. These
colors do not have to be the 16 MS-Windows standard colors. Padding each line with zeros up to a 32bit boundary
will result in up to 28 zeros = 7 'wasted pixels'.
Raster Data encoding for 8bit / 256 color images:
BitCount = 8 Compression = 0
Every byte holds 1 pixel. There are 256 color table entries. Padding each line with zeros up to a 32bit boundary will
result in up to 3 bytes of zeros = 3 'wasted pixels'.
Raster Data encoding for 16bit / hicolor images:
BitCount = 16 Compression = 0
Every 2bytes / 16bit holds 1 pixel.
<information missing: the 16 bit was introduced together with Video For Windows? Is it a memory-only-format?>
The pixels are no color table pointers. There are no color table entries. Padding each line with zeros up to a 16bit
boundary will result in up to 2 zero bytes.
Raster Data encoding for 24bit / truecolor images:
BitCount = 24 Compression = 0
Every 4bytes / 32bit holds 1 pixel. The first holds its red, the second its green, and the third its blue intensity. The
fourth byte is reserved and should be zero. There are no color table entries. The pixels are no color table pointers. No
zero padding necessary.
Raster Data compression for 4bit / 16 color images:
BitCount = 4 Compression = 2
The pixel data is stored in 2bytes / 16bit chunks. The first of these specifies the number of consecutive pixels with the
same pair of color. The second byte defines two color indices. The resulting pixel pattern will be interleaved
high-order 4bits and low order 4 bits (ABABA...). If the first byte is zero, the second defines an escape code. The
End-of-Bitmap is zero padded to end on a 32bit boundary. Due to the 16bit-ness of this structure this will always be
either two zero bytes or none.
n (byte 1) c (Byte 2) Description
>0 any n pixels are to be drawn. The 1st, 3rd, 5th, ... pixels' color is in c's high-order 4 bits, the even
pixels' color is in c's low-order 4 bits. If both color indices are the same, it results in just n
pixels of color c
0 0 End-of-line
0 1 End-of-Bitmap
0 2 Delta. The following 2 bytes define an unsigned offset in x and y direction (y being up) The
skipped pixels should get a color zero.
0 >=3 The following c bytes will be read as single pixel colors just as in uncompressed files. up to 12
bits of zeros follow, to put the file/memory pointer on a 16bit boundary again.
Example for 4bit RLE
Compressed Data Expanded data
03 04 0 4 0
05 06 0 6 0 6 0
00 06 45 56 67 00 4 5 5 6 6 7
04 78 7 8 7 8
00 02 05 01 Move 5 right and 1 up. (Windows docs say down, which is wrong)
00 00 End-of-line
09 1E 1 E 1 E 1 E 1 E 1
00 01 EndofBitmap
00 00 Zero padding for 32bit boundary
Raster Data compression for 8bit / 256 color images:
BitCount = 8 Compression = 1
The pixel data is stored in 2bytes / 16bit chunks. The first of these specifies the number of consecutive pixels with the
same color. The second byte defines their color index. If the first byte is zero, the second defines an escape code. The
End-of-Bitmap is zero padded to end on a 32bit boundary. Due to the 16bit-ness of this structure this will always be
either two zero bytes or none.
n (byte 1) c (Byte 2) Description
>0 any n pixels of color number c
0 0 End-of-line
0 1 End Of Bitmap
0 2 Delta. The following 2 bytes define an unsigned offset in x and y direction (y being up) The
skipped pixels should get a color zero.
0 >=3 The following c bytes will be read as single pixel colors just as in uncompressed files. A zero
follows, if c is odd, putting the file/memory pointer on a 16bit boundary again.
Example for 8bit RLE
Compressed Data Expanded data
03 04 04 04 04
05 06 06 06 06 06 06
00 03 45 56 67 00 45 56 67
02 78 78 78
00 02 05 01 Move 5 right and 1 up. (Windows docs say down, which is wrong)
00 00 End-of-line
09 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E
00 01 End-of-bitmap
00 00 Zero padding for 32bit boundary
Portability:
Although BMPs were invented by Microsoft for its Windows platform, a lot of programs on other platforms are capable
of reading and writing them. Notice the Intel order in 2byte and 4-byte integer values (Least significant byte first). The
16bit BMPs have been introduced to Windows after the others, still puzzling many applications.
Trademarks, Patents and Royalties
To my knowledge: None.
class initialization
-
initialize
-
tell Image-class, that a new fileReader is present
for the '.bmp' and '.ico' extensions.
testing
-
canRepresent: anImage
-
return true, if anImage can be represented in my file format.
BMP supports depth 1,4,8, 24 and 32.
-
isValidImageStream: inStream
-
return true, if inStream possibly contains an image in a format
which this reader class understands.
The stream is left open and position undefined afterwards.
accessing
-
image
-
(comment from inherited method)
return the image as represented by myself;
If my file contained multiple images, return the first one.
private
-
bitsPerPixel
-
-
convertPixels
-
figure out, how pixels should be processed,
-
loadBMP1From: aStream into: aByteArray
-
load bmp-1 bit per pixel imagedata.
-
loadBMP2From: aStream into: aByteArray
-
load bmp-2 bit per pixel imagedata.
-
loadBMP4From: aStream into: aByteArray
-
load bmp-4 bit per pixel imagedata.
-
loadBMP8From: aStream into: aByteArray
-
load bmp-8 bit per pixel imagedata.
-
loadBMPWidth: w height: h bytesPerPixel: bpp from: aStream into: aByteArray
-
load bmp-16/24/32 bit per pixel imagedata.
-
loadBMPWidth: w height: h depth: d from: aStream into: aByteArray
-
helper: load a BMP image
-
loadRLECompressedBMP4From: aStream into: aByteArray
-
load bmp-rle-4 pixel imagedata
-
loadRLECompressedBMP8From: aStream into: aByteArray
-
load bmp-8 bit per pixel imagedata
-
loadUncompressedFrom: aStream into: aByteArray
-
load bmp-1,2,4 and 8 bit per pixel imagedata.
-
readColorMap: nColors numBytesPerColor: nRawBytesPerColor from: aStream
-
read the colormap; notice: its in BGR order (sigh).
-
swapBytesFromRGBA_to_BGRA
-
Depth32Image keeps its data r/g/b/a; BMP has it b/g/r/a (sigh)
-
swapBytesFromRGB_to_BGR
-
Depth24Image keeps its data r/g/b; BMP has it b/g/r (sigh)
reading
-
fromOS2File: aFilename
-
read an image from an OS/2 BMP file
-
fromOS2Stream: aStream
-
read an image from an OS/2 BMP stream
-
fromOS2Stream: aStream alreadyRead: bytesAlreadyRead
-
read an image from an OS/2 BMP stream
-
fromStream: aStream
-
figure out which format the stream contains
(there are various different bmp/ico formats around)
and read the image.
-
fromWindowsBMPFile: aFilename
-
read an image from a windows BMP file
-
fromWindowsBMPStream: aStream
-
read an image from a windows BMP stream
-
fromWindowsBMPStream: aStream alreadyRead: fileHeaerBytesAlreadyRead
-
read an image from a windows BMP stream
-
fromWindowsICOFile: aFilename
-
read an image from a windows ICO file
-
fromWindowsICOStream: aStream
-
read an image from a windows ICO stream
-
fromWindowsICOStream: aStream alreadyRead: bytesAlreadyRead
-
read an image from a windows ICO stream
-
old_fromWindowsICOStream: aStream alreadyRead: bytesAlreadyRead
-
read an image from a windows ICO stream
-
readSingleImageFromWindowsICOStream: aStream
-
read one image from a windows ICO stream
writing
-
save: image onFile: aFilenameOrFilenameString
-
save image as BMP file on aFileName.
Only depth 1,4,8 and 24 images can be represented in this format.
-
saveBMP: image onFile: fileName
-
save image as BMP file on aFileName.
Only depth 1,4,8 and 24 images can be represented in this format.
-
saveBMP: imageArg withFileHeader: withFileHeaderBoolean onStream: aStream
-
save image as BMP file on aFileName.
If withFileHeaderBoolean is false, no bitmapFileHeader is written (used when saving ICO files).
Only depth 1,4,8 and 24 images can be represented in this format.
-
saveICO: image onFile: fileName
-
save image as ICO file on aFileName
Usage example(s):
|i|
i := Image fromFile:'bitmaps/xpmBitmaps/SmalltalkX_clr.xpm'.
i := Depth4Image fromImage:i.
i := i magnifiedTo:32@32.
WindowsIconReader new saveICO:i onFile:'test.ico'.
|
|