--- a/WindowsIconReader.st Wed Oct 15 19:58:09 1997 +0200
+++ b/WindowsIconReader.st Tue Oct 21 20:27:06 1997 +0200
@@ -10,6 +10,8 @@
hereby transferred.
"
+'From Smalltalk/X, Version:3.2.1 on 21-oct-1997 at 5:07:02 pm' !
+
ImageReader subclass:#WindowsIconReader
instanceVariableNames:''
classVariableNames:''
@@ -36,7 +38,7 @@
documentation
"
this class provides methods for loading Windows and OS2 icon files.
- Image writing is not supported.
+ 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 ...
@@ -63,6 +65,15 @@
!WindowsIconReader class methodsFor:'testing'!
+canRepresent:anImage
+ "return true, if anImage can be represented in my file format.
+ BMP supports depth 1,4,8 and 24."
+
+ ^ (#(1 4 8 24) includes:anImage depth)
+
+ "Created: 17.10.1997 / 20:18:23 / cg"
+!
+
isValidImageFile:aFileName
"return true, if aFileName contains a valid windows bitmap-file image"
@@ -113,7 +124,7 @@
loadBMPWidth:w height:h depth:d compression:c from:aStream into:data
"helper: load a BMP image"
- |buff idx1 idx2 bytesPerRow|
+ |buff idx fileBytesPerRow imgBytesPerRow|
d == 8 ifTrue:[
(self class loadBMP8Width:w height:h compression:c from:aStream into:data) ifFalse:[
@@ -144,29 +155,31 @@
^ true
].
d == 24 ifTrue:[
- bytesPerRow := w * 3.
- ((aStream nextBytes:(h * bytesPerRow) into:data) ~~ (h * bytesPerRow)) ifTrue:[
- 'WinIconReader [warning]: read failed' infoPrintNL.
- ^ false
+ imgBytesPerRow := w * 3.
+ fileBytesPerRow := imgBytesPerRow.
+ (fileBytesPerRow bitAnd:3) ~~ 0 ifTrue:[
+ fileBytesPerRow := (fileBytesPerRow bitAnd:(3 bitInvert)) + 4.
].
+ "/
"/ stupid - last row comes first
+ "/
+ idx := imgBytesPerRow * (height - 1) + 1.
+ buff := ByteArray uninitializedNew:fileBytesPerRow.
- buff := ByteArray uninitializedNew:bytesPerRow.
- idx1 := 1.
- idx2 := 1 + (h-1 * bytesPerRow).
- [idx1 < idx2] whileTrue:[
- buff replaceFrom:1 to:bytesPerRow with:data startingAt:idx1.
- data replaceFrom:idx1 to:(idx1 + bytesPerRow - 1) with:data startingAt:idx2.
- data replaceFrom:idx2 to:(idx2 + bytesPerRow - 1) with:buff startingAt:1.
- idx1 := idx1 + bytesPerRow.
- idx2 := idx2 - bytesPerRow.
+ 1 to:height do:[:row |
+ (aStream nextBytes:fileBytesPerRow into:buff) ~~ fileBytesPerRow ifTrue:[
+ 'WinIconReader [warning]: read failed' infoPrintNL.
+ ^ false
+ ].
+ data replaceFrom:idx to:idx+imgBytesPerRow-1 with:buff.
+ idx := idx - imgBytesPerRow.
].
^ true
].
'WinIconReader [warning]: unsupported depth:' infoPrint. d infoPrintNL.
"Created: 17.9.1995 / 18:48:11 / claus"
- "Modified: 28.1.1997 / 01:46:07 / cg"
+ "Modified: 19.10.1997 / 00:01:56 / cg"
! !
!WindowsIconReader methodsFor:'reading from file'!
@@ -665,9 +678,126 @@
"Modified: 24.4.1997 / 22:03:48 / cg"
! !
+!WindowsIconReader methodsFor:'writing to file'!
+
+save:image onFile:aFileName
+ "save image as BMP file on aFileName.
+ Only depth 1,4,8 and 24 images can be represented in this format."
+
+ self saveBMP:image onFile:aFileName.
+
+ "Modified: 17.10.1997 / 20:16:53 / cg"
+!
+
+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."
+
+ |depth bhSize biSize biClrUsed biSizeImage bfOffBits rowBytes imgBytesPerRow data srcIndex row|
+
+ depth := image depth.
+ width := image width.
+ height := image height.
+
+ (#(1 4 8 24) includes:depth) ifFalse:[
+ ^ Image cannotRepresentImageSignal
+ raiseWith:image
+ errorString:('BMP format only supports depths 1,4,8 and 24').
+ ].
+ image mask notNil ifTrue:[
+ Image informationLostQuerySignal
+ raiseWith:image
+ errorString:('BMP format does not support an imageMask').
+ ].
+
+ bhSize := 14. "# bytes in file header"
+ biSize := 40. "info header size in bytes"
+ biClrUsed := (depth >= 24) ifTrue:[0] ifFalse:[1 << depth]. "No. color table entries"
+ bfOffBits := biSize + bhSize + (4*biClrUsed).
+ "/ bmp aligns rows on a longword boundary
+ rowBytes := ((depth min:24) * width + 31 // 32) * 4.
+ biSizeImage := height * rowBytes.
+
+ outStream := fileName asFilename writeStream.
+ outStream binary.
+ byteOrder := #lsb.
+
+ "Write the file header"
+ self writeShort:19778. "bfType = BM"
+ self writeLong:(bfOffBits + biSizeImage). "Entire file size in bytes"
+ self writeLong:0. "bfReserved"
+ self writeLong:bfOffBits. "Offset of bitmap data from start of hdr (and file)"
+
+ "Write the bitmap info header"
+ outStream position: bhSize+1.
+ self writeLong:biSize. "info header size in bytes"
+ self writeLong:width. "biWidth"
+ self writeLong:height. "biHeight"
+ self writeShort:1. "biPlanes"
+ self writeShort:(depth min:24). "biBitCount"
+ self writeLong:0. "biCompression"
+ self writeLong:biSizeImage. "size of image section in bytes"
+ self writeLong:2800. "biXPelsPerMeter"
+ self writeLong:2800. "biYPelsPerMeter"
+ self writeLong:biClrUsed.
+ self writeLong:0. "biClrImportant"
+ 1 to:biClrUsed do:[:i | "Color map"
+ |clr r g b|
+
+ clr := image colorFromValue:i-1.
+ clr isNil ifTrue:[
+ r := g := b := 0.
+ ] ifFalse:[
+ r := clr redByte.
+ g := clr greenByte.
+ b := clr blueByte.
+ ].
+
+ "/ put B,G,R
+ outStream nextPut:b.
+ outStream nextPut:g.
+ outStream nextPut:r.
+ outStream nextPut:0.
+ ].
+
+ imgBytesPerRow := image bytesPerRow.
+ data := image data.
+
+
+ "/ sorry, must extract rows individually
+ "/ (even if alignment is correct),
+ "/ since BMP saves rows bottom-to-top
+
+ row := ByteArray new:rowBytes.
+
+ srcIndex := 1 + (height * imgBytesPerRow).
+ 1 to:height do:[:i |
+ srcIndex := srcIndex - imgBytesPerRow.
+ row replaceFrom:1 to:imgBytesPerRow with:data startingAt:srcIndex.
+ outStream nextPutAll:row.
+ ].
+
+ outStream close.
+
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/SBrowser.xbm'.
+ WindowsIconReader save:i onFile:'test.bmp'.
+ "
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/gifImages/garfield.gif'.
+ WindowsIconReader save:i onFile:'test.bmp'.
+ "
+
+ "Modified: 21.10.1997 / 05:02:02 / cg"
+! !
+
!WindowsIconReader class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview2/WindowsIconReader.st,v 1.36 1997-09-10 21:28:18 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview2/WindowsIconReader.st,v 1.37 1997-10-21 18:27:06 cg Exp $'
! !
WindowsIconReader initialize!