--- a/Image.st Mon Feb 06 01:30:10 1995 +0100
+++ b/Image.st Mon Feb 06 01:38:04 1995 +0100
@@ -28,7 +28,7 @@
COPYRIGHT (c) 1991 by Claus Gittinger
All Rights Reserved
-$Header: /cvs/stx/stx/libview/Image.st,v 1.18 1994-11-28 21:00:57 claus Exp $
+$Header: /cvs/stx/stx/libview/Image.st,v 1.19 1995-02-06 00:37:05 claus Exp $
'!
!Image class methodsFor:'documentation'!
@@ -49,7 +49,7 @@
version
"
-$Header: /cvs/stx/stx/libview/Image.st,v 1.18 1994-11-28 21:00:57 claus Exp $
+$Header: /cvs/stx/stx/libview/Image.st,v 1.19 1995-02-06 00:37:05 claus Exp $
"
!
@@ -138,6 +138,12 @@
"
! !
+!Image class methodsFor:'queries'!
+
+imageDepth
+ self shouldNotImplement
+! !
+
!Image class methodsFor:'misc'!
dither:aSymbol
@@ -280,7 +286,11 @@
!
fromView:aView
- "return an image taken from a view"
+ "return an image taken from a views contents as currently
+ on the screen. The returned image has the same depth and photometric
+ as the Display. Notice, that for invisible or partial covered
+ views, the returned Image is NOT correct. You may want to raise
+ the view before using this method."
|org dev|
@@ -290,39 +300,112 @@
to:(DisplayRootView on:dev) id.
^ self fromScreen:(org extent:aView extent) on:dev
- "Image fromView:(Launcher allInstances first topView)"
- "Image fromView:(SystemBrowser allInstances first topView)"
+ "
+ Image fromView:(Launcher allInstances first topView)
+ Image fromView:(SystemBrowser allInstances first topView)
+ "
! !
!Image class methodsFor:'instance creation'!
+new
+ "create a new image. Redefined to set the photometric to
+ greyScale with black being 0 as default."
+
+ ^ super new photometric:#blackIs0
+!
+
+fromForm:aForm
+ "create & return an Image given a form"
+
+ |cls|
+
+ cls := self.
+ cls == Image ifTrue:[
+ cls := self implementorForDepth:aForm depth
+ ].
+ ^ (cls new) fromForm:aForm.
+
+ "
+ |f|
+
+ f := Form width:16 height:16.
+ f clear.
+ f displayLineFromX:0 y:0 toX:15 y:15.
+ f inspect.
+ (Image fromForm:f) inspect
+ "
+!
+
+fromImage:anImage
+ "create & return an Image given another image. This can be used to
+ convert an image to another depth."
+
+ (self == Image or:[anImage class == self]) ifTrue:[^ anImage].
+ ^ self new fromImage:anImage.
+
+ "
+ |i1 i8|
+
+ i1 := Image fromFile:'bitmaps/SBrowser.xbm'.
+ i8 := Depth8Image fromImage:i1.
+ i8 inspect
+ "
+!
+
+width:w height:h
+ "create a new image, given width, height. Assume a depth of 1."
+
+ |cls|
+
+ cls := self.
+ cls == Image ifTrue:[
+ cls := self implementorForDepth:1
+ ].
+ ^ cls new width:w height:h depth:1
+!
+
width:w height:h depth:d
- "create a new form on the default device"
-
- ^ (self implementorForDepth:d) new width:w height:h depth:d
+ "create a new image, given width, height and depth"
+
+ ^ (self implementorForDepth:d) width:w height:h depth:d
!
width:w height:h fromArray:anArray
- "create a new form on the default device - assume depth of 1"
-
- ^ (self implementorForDepth:1) new width:w height:h depth:1 fromArray:anArray
+ "create a new image, given width, height. Assume a depth of 1 of the
+ receiving class is Image.
+ Data must be a ByteArray containing correctly aligned bits for depth 1
+ (i.e. 8 bits per byte)."
+
+ |cls d|
+
+ cls := self.
+ cls == Image ifTrue:[
+ cls := self implementorForDepth:1.
+ d := 1.
+ ] ifFalse:[
+ d := cls imageDepth
+ ].
+ ^ cls new width:w height:h depth:d fromArray:anArray
"
Image width:8
height:8
- fromArray:#(2r11001100
+ fromArray:#[2r11001100
2r00110011
2r11001100
2r00110011
2r11001100
2r00110011
2r11001100
- 2r00110011).
+ 2r00110011].
"
!
width:w height:h depth:d fromArray:pixelData
- "create a new form on the default device"
+ "create a new image, given width, height, depth and data.
+ Data must be a ByteArray containing correctly aligned bits for the specified
+ depth."
^ (self implementorForDepth:d) new width:w height:h depth:d fromArray:pixelData
@@ -330,28 +413,42 @@
Image width:8
height:8
depth:1
- fromArray:#(2r11001100
+ fromArray:#[2r11001100
2r00110011
2r11001100
2r00110011
2r11001100
2r00110011
2r11001100
- 2r00110011).
+ 2r00110011].
"
"
Image width:8
height:8
depth:2
- fromArray:#(4r1100 4r1100
+ fromArray:#[4r1100 4r1100
4r0011 4r0011
4r1100 4r1100
4r0011 4r0011
4r1100 4r1100
4r0011 4r0011
4r1100 4r1100
- 4r0011 4r0011).
+ 4r0011 4r0011].
+ "
+
+ "
+ Image width:8
+ height:8
+ depth:4
+ fromArray:#[4r0001 4r0001
+ 4r0011 4r0011
+ 4r1100 4r1100
+ 4r0011 4r0011
+ 4r1100 4r1100
+ 4r0011 4r0011
+ 4r1100 4r1100
+ 4r0011 4r0011].
"
! !
@@ -362,27 +459,31 @@
out the file format itself (by the extension and by contents)
and lets the appropriate reader read the file."
- |readerClass image name|
+ |image name nm|
"
before trying each reader, check if file is readable
"
- aFileName asFilename isReadable ifFalse:[
- ('IMAGE: ' , aFileName , ' is not existing or not readable') errorPrintNL.
- ^ nil
+ name := aFileName.
+ name asFilename isReadable ifFalse:[
+ name := 'bitmaps/' , name.
+ name asFilename isReadable ifFalse:[
+ ('IMAGE: ' , aFileName , ' is not existing or not readable') errorPrintNL.
+ ^ nil
+ ].
].
"
get the imageReader class from the files extension
"
- name := aFileName.
+ nm := name.
(name endsWith:'.Z') ifTrue:[
- name := name copyTo:(name size - 2)
+ nm := name copyTo:(name size - 2)
].
FileFormats keysAndValuesDo:[:suffix :readerClass |
- (name endsWith:suffix) ifTrue:[
+ (nm endsWith:suffix) ifTrue:[
readerClass notNil ifTrue:[
- image := readerClass fromFile:aFileName.
+ image := readerClass fromFile:name.
image notNil ifTrue:[^ image].
]
]
@@ -394,8 +495,8 @@
"
FileFormats do:[:readerClass |
readerClass notNil ifTrue:[
- (readerClass isValidImageFile:aFileName) ifTrue:[
- ^ readerClass fromFile:aFileName
+ (readerClass isValidImageFile:name) ifTrue:[
+ ^ readerClass fromFile:name
]
]
].
@@ -404,21 +505,23 @@
'IMAGE: unknown image file format: ' errorPrint. aFileName errorPrintNL.
^ nil
- "Image fromFile:'bitmaps/dano.tiff'"
- "Image fromFile:'bitmaps/test.fax'"
- "Image fromFile:'bitmaps/voice.tiff'"
- "Image fromFile:'voice.tiff'"
-
- "Image fromFile:'../fileIn/bitmaps/claus.gif'"
- "Image fromFile:'../fileIn/bitmaps/garfield.gif'"
-
- "Image fromFile:'../fileIn/bitmaps/founders.im8'"
- "Image fromFile:'../goodies/faces/next.com/steve.face'"
-
- "Image fromFile:'/LocalLibrary/Images/OS2/dos3.ico'"
- "Image fromFile:'bitmaps/globe1.xbm'"
- "Image fromFile:'bitmaps/globe1.xbm.Z'"
- "Image fromFile:'bitmaps/hello_world.icon'"
+ "
+ Image fromFile:'bitmaps/dano.tiff'
+ Image fromFile:'bitmaps/test.fax'
+ Image fromFile:'bitmaps/voice.tiff'
+ Image fromFile:'voice.tiff'
+
+ Image fromFile:'../fileIn/bitmaps/claus.gif'
+ Image fromFile:'../fileIn/bitmaps/garfield.gif'
+
+ Image fromFile:'../fileIn/bitmaps/founders.im8'
+ Image fromFile:'../goodies/faces/next.com/steve.face'
+
+ Image fromFile:'/LocalLibrary/Images/OS2/dos3.ico'
+ Image fromFile:'bitmaps/globe1.xbm'
+ Image fromFile:'bitmaps/globe1.xbm.Z'
+ Image fromFile:'bitmaps/hello_world.icon'
+ "
! !
!Image class methodsFor:'queries'!
@@ -682,7 +785,29 @@
very slow ...
(it is meant to access individual pixels - for example, in a bitmap editor)"
- ^ self subclassResponsibility
+ |pixel maxPixel r g b|
+
+ pixel := self valueAtX:x y:y.
+ photometric == #blackIs0 ifTrue:[
+ maxPixel := (1 bitShift:self bitsPerPixel) - 1.
+ ^ Color grey:(pixel * (100 / maxPixel)).
+ ].
+ photometric == #whiteIs0 ifTrue:[
+ maxPixel := (1 bitShift:self bitsPerPixel) - 1.
+ ^ Color grey:100 - (pixel * (100 / maxPixel)).
+ ].
+ photometric == #palette ifTrue:[
+ ^ colorMap at:(pixel + 1)
+ ].
+ photometric == #rgb ifTrue:[
+ r := (pixel bitShift:16) bitAnd:16rFF.
+ g := (pixel bitShift:8) bitAnd:16rFF.
+ b := pixel bitAnd:16rFF.
+ ^ Color red:r / 255 * 100
+ green:g / 255 * 100
+ blue:b / 255 * 100
+ ].
+ self error:'invalid photometric'
!
at:aPoint put:aColor
@@ -700,11 +825,36 @@
"set the pixel at x/y to aColor.
Pixels start at 0@0 for the upper left pixel, end at
(width-1)@(height-1) for the lower right pixel.
- You should not use this method for image-processing, its
- very slow ...
+ This method checks if the color can be stored in the image.
+ (i.e. if the receiver is a palette image, the color must be present in there).
+ You should not use this method for image-processing, it is very slow ...
(it is meant to access individual pixels - for example, in a bitmap editor)"
- ^ self subclassResponsibility
+ |pixel maxPixel|
+
+ photometric == #whiteIs0 ifTrue:[
+ maxPixel := (1 bitShift:self bitsPerPixel) - 1.
+ pixel := maxPixel - (aColor brightness * maxPixel) rounded.
+ ] ifFalse:[
+ photometric == #blackIs0 ifTrue:[
+ maxPixel := (1 bitShift:self bitsPerPixel) - 1.
+ pixel := (aColor brightness * maxPixel) rounded.
+ ] ifFalse:[
+ photometric ~~ #palette ifTrue:[
+ self error:'format not supported'.
+ ^ nil
+ ].
+ pixel := colorMap indexOf:aColor.
+ pixel == 0 ifTrue:[
+ "
+ the color to be stored is not in the images colormap
+ "
+ self error:'invalid color'
+ ].
+ pixel := pixel - 1
+ ]
+ ].
+ self atX:x y:y putValue:pixel.
!
valueAt:aPoint
@@ -746,7 +896,7 @@
^ self subclassResponsibility
! !
-!Image methodsFor:'enumeration'!
+!Image methodsFor:'enumerating'!
valueAtY:y from:x1 to:x2 do:aBlock
"perform aBlock for each pixelValue from x1 to x2 in row y.
@@ -828,6 +978,15 @@
!Image methodsFor:'queries'!
+brightness
+ "return the brightness of the image.
+ This usually only makes sense for textures and patterns
+ (i.e. to compute shadow & light colors for viewBackgrounds).
+ Notice, that for the above purpose, only a subimage is inspected here"
+
+ ^ (self averageColorIn:(0@0 corner:7@7)) brightness
+!
+
averageColor
"return the average color of the image.
This usually only makes sense for textures and patterns
@@ -889,6 +1048,48 @@
bytesPerRow := bytesPerRow + 1
].
^ bytesPerRow
+!
+
+usedValues
+ "return a collection of color values used in the receiver.
+ Notice, that the interpretation of the pixels depends on the photometric
+ of the image.
+ This is a general and therefore slow implementation; subclasses
+ may want to redefine this method for more performance."
+
+ |set|
+
+ set := IdentitySet new.
+ self valuesFromX:0 y:0 toX:(self width-1) y:(self height-1) do:[:x :y :pixel |
+ set add:pixel
+ ].
+ ^ set
+
+ "
+ (Image fromFile:'bitmaps/garfield.gif') usedValues
+ (Image fromFile:'bitmaps/SBrowser.xbm') usedValues
+ (Image fromFile:'ttt.tiff') usedValues
+ "
+!
+
+usedColors
+ "return a collection of colors used in the receiver."
+
+ |usedValues max|
+
+ usedValues := self usedValues asArray.
+ photometric ~~ #palette ifTrue:[
+ max := (1 bitShift:self depth) - 1.
+ ^ usedValues collect:[:val | (Color grey:(100 * val / max ))]
+ ].
+
+ ^ usedValues collect:[:val | (colorMap at:val+1)]
+
+ "
+ (Image fromFile:'bitmaps/garfield.gif') usedColors
+ (Image fromFile:'bitmaps/SBrowser.xbm') usedColors
+ (Image fromFile:'ttt.tiff') usedColors
+ "
! !
!Image methodsFor:'printing & storing'!
@@ -930,8 +1131,8 @@
h "{ Class: SmallInteger }"
dstIndex "{ Class: SmallInteger }"
srcIndex "{ Class: SmallInteger }"
- inData tmpData usedColors nUsed
- rMap gMap bMap bitsPerPixel bytesPerLine
+ inData tmpData usedPixels mapSize
+ map bitsPerPixel bytesPerLine
info bytesPerLineIn curs cid rootView|
curs := Cursor sourceForm:(Form fromFile:'Camera.xbm')
@@ -1038,25 +1239,20 @@
what we have now are the color numbers - still need the r/g/b values.
find out, which colors are in the picture
"
- usedColors := inData usedValues.
- nUsed := usedColors max + 1.
+ usedPixels := inData usedValues.
+ mapSize := usedPixels max + 1.
"get the palette"
- rMap := Array new:nUsed.
- gMap := Array new:nUsed.
- bMap := Array new:nUsed.
- usedColors do:[:colorIndex |
- |i scale|
+ map := Array new:mapSize.
+ usedPixels do:[:colorIndex |
+ |i|
i := colorIndex + 1.
- scale := 255.0 / 100.0.
aDevice getRGBFrom:colorIndex into:[:r :g :b |
- rMap at:i put:(r * scale) rounded.
- gMap at:i put:(g * scale) rounded.
- bMap at:i put:(b * scale) rounded
+ map at:i put:(Color red:r green:g blue:b)
]
].
- colorMap := Array with:rMap with:gMap with:bMap.
+ colorMap := map.
].
aDevice ungrabPointer.
@@ -1212,6 +1408,105 @@
].
^ form
+!
+
+fromImage:anImage
+ "setup the receiver from another image.
+ Color precision may be lost, if conversion is from a higher depth
+ image. This implementation is a slow fallback (the loop over the
+ source pixels is very slow). If this method is used heavily, you
+ may want to redefine it in concrete subclasses for common source images."
+
+ width := anImage width.
+ height := anImage height.
+ bytes := ByteArray uninitializedNew:(self bytesPerRow * height).
+ bitsPerSample := self bitsPerSample.
+ samplesPerPixel := self samplesPerPixel.
+ samplesPerPixel == 3 ifTrue:[
+ photometric := #rgb
+ ] ifFalse:[
+ photometric := anImage photometric.
+ photometric == #palette ifTrue:[
+ colorMap := anImage colorMap copy.
+ "
+ must compress the colormap, if source image has higher depth
+ than myself.
+ "
+ anImage bitsPerPixel > self bitsPerPixel ifTrue:[
+ "
+ get used colors are extracted into our colorMap
+ (the at-put below will set the pixelValue according the
+ new colorIndex
+ "
+ colorMap := anImage usedColors asArray.
+ colorMap size > (1 bitShift:self bitsPerPixel) ifTrue:[
+ 'IMAGE: possibly too many colors in image' errorPrintNL
+ ]
+ ]
+ ]
+ ].
+ anImage colorsFromX:0 y:0 toX:(width-1) y:(height-1) do:[:x :y :clr |
+ self atX:x y:y put:clr
+ ].
+
+ "
+ |i i2 i4 i8 i24|
+
+ i := Image fromFile:'bitmaps/SBrowser.xbm'.
+ i inspect.
+ i2 := Depth2Image fromImage:i.
+ i2 inspect.
+ i4 := Depth4Image fromImage:i.
+ i4 inspect.
+ i8 := Depth8Image fromImage:i.
+ i8 inspect.
+ i24 := Depth24Image fromImage:i.
+ i24 inspect.
+ "
+!
+
+fromForm:aForm
+ "setup receiver from a form"
+
+ |newImage cls map c0 c1 redMap greenMap blueMap|
+
+ width := aForm width.
+ height := aForm height.
+ bytes := aForm bits.
+ bitsPerSample := self bitsPerSample.
+ samplesPerPixel := self samplesPerPixel.
+ map := aForm colorMap.
+
+ aForm depth == 1 ifTrue:[
+ map isNil ifTrue:[
+ photometric := #whiteIs0
+ ] ifFalse:[
+ c0 := map at:1.
+ c1 := map at:2.
+ ((c0 = Color white)
+ and:[c1 = Color black]) ifTrue:[
+ photometric := #whiteIs0
+ ] ifFalse:[
+ ((c0 = Color black)
+ and:[c1 = Color white]) ifTrue:[
+ photometric := #blackIs0
+ ] ifFalse:[
+ photometric := #palette.
+ colorMap := Array with:c0 with:c1.
+ ]
+ ]
+ ]
+ ] ifFalse:[
+ map notNil ifTrue:[
+ photometric := #palette.
+ colorMap := map copy.
+ ] ifFalse:[
+ "
+ photometric stays at default
+ (which is rgb for d24, greyscale for others)
+ "
+ ]
+ ].
! !
!Image methodsFor:'converting rgb images'!
@@ -1353,6 +1648,26 @@
paletteImageAsPseudoFormOn:aDevice
"return a pseudo-deviceForm from the palette image."
+ |tempImage d temp8|
+
+ d := self depth.
+ (#(1 2 4 8) includes:d) ifTrue:[
+ "
+ fallback code for some depth's:
+ create a temporary Depth8Image and use its conversion method
+ "
+ temp8 := ByteArray uninitializedNew:(width * height).
+
+ bytes expandPixels:d
+ width:width
+ height:height
+ into:temp8
+ mapping:nil.
+
+ tempImage := Image width:width height:height depth:8 fromArray:temp8.
+ tempImage colorMap:colorMap.
+ ^ tempImage paletteImageAsPseudoFormOn:aDevice
+ ].
^ self subclassResponsibility
!
@@ -1653,10 +1968,12 @@
!Image methodsFor:'image manipulations'!
-copyWithColorMapProcessingRed:rBlock green:gBlock blue:bBlock
+copyWithColorMapProcessing:aBlock
"a helper to create & return new images based on the receiver with
- some colorMap processing. The arguments are called
- for each color component and are supposed to return new values."
+ some colorMap processing. The receiver is copied, and the copied images
+ colormap is modified by replacing entries with the result of the processing block,
+ which is called with the original color values. The block is supposed to return
+ a color."
|newImage|
@@ -1670,94 +1987,84 @@
the code below manipulates the colormap.
For non-palette images, special code is required
"
- newImage colorMapProcessingRed:rBlock green:gBlock blue:bBlock.
+ newImage colorMapProcessing:aBlock.
^ newImage
"
leave red component only:
(Image fromFile:'bitmaps/claus.gif')
- copyWithColorMapProcessingRed:[:r | r]
- green:[:g | 0]
- blue:[:b | 0]
+ copyWithColorMapProcessing:[:clr | Color red:(clr red) green:0 blue:0]
"
+
"
make it reddish:
(Image fromFile:'bitmaps/claus.gif')
- copyWithColorMapProcessingRed:[:r | (r * 2) min:255]
- green:[:g | g]
- blue:[:b | b]
+ copyWithColorMapProcessing:[:clr | Color red:((clr red * 2) min:100) green:clr green blue:clr blue]
"
+
"
invert:
(Image fromFile:'bitmaps/claus.gif')
- copyWithColorMapProcessingRed:[:r | 255-r]
- green:[:g | 255-g]
- blue:[:b | 255-b]
+ copyWithColorMapProcessing:[:clr | Color red:(100 - clr red) green:(100 - clr green) blue:(100 - clr green)]
"
+
"
lighter:
(Image fromFile:'bitmaps/claus.gif')
- copyWithColorMapProcessingRed:[:r | r + (255-r//2)]
- green:[:g | g + (255-g//2)]
- blue:[:b | b + (255-b//2)]
+ copyWithColorMapProcessing:[:clr | |r g b|
+ r := clr red. g := clr green. b := clr blue.
+ Color red:(r + (100-r//2))
+ green:(g + (100-g//2))
+ blue:(b + (100-b//2))]
"
+
"
darker:
(Image fromFile:'bitmaps/claus.gif')
- copyWithColorMapProcessingRed:[:r | r//2]
- green:[:g | g//2]
- blue:[:b | b//2]
+ copyWithColorMapProcessing:[:clr | Color red:(clr red//2) green:(clr green // 2) blue:(clr blue // 2)]
"
!
-colorMapProcessingRed:rBlock green:gBlock blue:bBlock
+colorMapProcessing:aBlock
"a helper for all kinds of colormap manipulations.
- The argument blocks are called for each pixel r/g/b and
- are supposed to return new r/g/b values.
+ The argument aBlocks is called for every colormap entry, and the returned value
+ will replace that entry in the map.
This will fail for non-palette images.
- see examples in Image>>copyWithColorMapProcessingRed:green:blue:"
-
- |rMap gMap bMap nColors|
+ see examples in Image>>copyWithColorMapProcessing:"
+
+ |nColors "{ Class: SmallInteger }"|
colorMap isNil ifTrue:[
^ self error:'image has no colormap'
].
- "
- the code below manipulates the colormap.
- For non-palette images, special code is required
- "
- rMap := colorMap at:1.
- gMap := colorMap at:2.
- bMap := colorMap at:3.
- nColors := rMap size.
-
+ nColors := colorMap size.
1 to:nColors do:[:index |
- |red green blue|
-
- red := (rMap at:index).
- green := (gMap at:index).
- blue := (bMap at:index).
-
- rMap at:index put:(rBlock value:red).
- gMap at:index put:(gBlock value:green).
- bMap at:index put:(bBlock value:blue).
+ |clr|
+
+ clr := colorMap at:index.
+ clr notNil ifTrue:[
+ colorMap at:index put:(aBlock value:clr)
+ ]
]
!
lightened
- "return a new image which is slightly darker than the receiver.
+ "return a new image which is slightly brighter than the receiver.
+ The receiver must be a palette image (currently).
Need an argument, which specifies by how much it should be lighter."
^ self
- copyWithColorMapProcessingRed:[:r | r + (255-r//2)]
- green:[:g | g + (255-g//2)]
- blue:[:b | b + (255-b//2)]
+ copyWithColorMapProcessing:[:clr | |r g b|
+ r := clr red. g := clr green. b := clr blue.
+ Color red:(r + (255-r//2))
+ green:(g + (255-g//2))
+ blue:(b + (255-b//2))]
"
(Image fromFile:'bitmaps/claus.gif') inspect
@@ -1769,12 +2076,11 @@
darkened
"return a new image which is slightly darker than the receiver.
+ The receiver must be a palette image (currently).
Need an argument, which specifies by how much it should be darker."
^ self
- copyWithColorMapProcessingRed:[:r | r // 2]
- green:[:g | g // 2]
- blue:[:b | b // 2]
+ copyWithColorMapProcessing:[:clr | Color red:(clr r // 2) green:(clr green // 2) blue:(clr blue // 2)]
"
(Image fromFile:'bitmaps/claus.gif') inspect
@@ -1929,6 +2235,16 @@
"((Image fromFile:'bitmaps/claus.gif') magnifyBy:0.5@0.5)"
!
+magnifyTo:anExtent
+ "return a new image magnified to have the size specified by extent."
+
+ ^ self magnifyBy:(anExtent / self extent)
+
+ "
+ ((Image fromFile:'bitmaps/garfield.gif') magnifyTo:100@100)
+ "
+!
+
flipHorizontal
"inplace horizontal flip"
@@ -2066,9 +2382,34 @@
!Image methodsFor: 'binary storage'!
+storeBinaryDefinitionOn: stream manager: manager
+ "store a binary representation of the receiver on stream.
+ Redefined to not store the device form (which is recreated at
+ load time anyway)"
+
+ |tDevice tDeviceForm tMonoDeviceForm tFullColorDeviceForm|
+
+ tDevice := device.
+ tDeviceForm := deviceForm.
+ tMonoDeviceForm := monoDeviceForm.
+ tFullColorDeviceForm := fullColorDeviceForm.
+
+ device := nil.
+ deviceForm := nil.
+ monoDeviceForm := nil.
+ fullColorDeviceForm := nil.
+
+ super storeBinaryDefinitionOn: stream manager: manager.
+
+ device := tDevice.
+ deviceForm := tDeviceForm.
+ monoDeviceForm := tMonoDeviceForm.
+ fullColorDeviceForm := tFullColorDeviceForm.
+!
+
readBinaryContentsFrom: stream manager: manager
"read a binary representation of an image from stream.
- Redefined to fLush any device data."
+ Redefined to flush any device data."
super readBinaryContentsFrom: stream manager: manager.
device := nil.