--- a/ImageEditor.st Mon Jul 27 18:20:47 1998 +0200
+++ b/ImageEditor.st Tue Jul 28 21:48:48 1998 +0200
@@ -788,7 +788,7 @@
)
)
#(#MenuItem
- #label: 'Color Map'
+ #label: 'ColorMap'
#translateLabel: true
#activeHelpKey: #colorMap
#enabled: #imageIsLoaded
@@ -855,6 +855,14 @@
#argument: '1-plane + mask'
#indication: #colorMapMode:value:
)
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Compress colormap'
+ #translateLabel: true
+ #value: #compressColorMap
+ )
) nil
nil
)
@@ -900,6 +908,8 @@
) nil
nil
)
+
+ "Modified: / 28.7.1998 / 20:03:52 / cg"
!
menuMouseButtonColors
@@ -1348,80 +1358,6 @@
^colorMapMode = aMode
!
-colorMapMode: aMode value: aValue
- "calculates a new color map for the image from aMode"
-
- |depth newColorMap newImage image newColors realColorMap oldFileName|
-
- imageEditView makeUndo.
-
- newColorMap := self class listOfColorMaps at: aMode.
- depth := (newColorMap size log: 2) asInteger.
- newImage := (Image implementorForDepth: depth) new.
- oldFileName := self image fileName.
-
- Object errorSignal handle:
- [:ex|
- Object errorSignal handle:
- [:ex|
- imageEditView undo.
- ^self warn: 'Convertation failed!!'
- ]
- do:
- [
- self image colorsFromX:0 y:0 toX:(self image width-1) y:(self image height-1) do:
- [:x :y :clr |
- (newColorMap includes: clr)
- ifTrue: [self image colorAtX:x y:y put:clr]
- ifFalse: [self image colorAtX:x y:y put: self image colorMap first]
- ].
- image := newImage fromImage: self image.
- ].
- ]
- do:
- [
- image := newImage fromImage: self image
- ].
-
- (String fromString: aMode) reverse readStream nextWord reverse = 'mask'
- ifTrue:
- [
- image mask isNil
- ifTrue:
- [
- image mask: (Depth1Image fromImage: (image asThresholdMonochromeImage: 0.1)).
- ].
- ]
- ifFalse:
- [
- image mask: nil.
- ].
- realColorMap := OrderedCollection new.
- image realColorMap do:
- [:clr|
- (realColorMap includes: clr) ifFalse: [realColorMap add: clr]
- ].
- newColors := realColorMap copyFrom: 1 to: (newColorMap size min: realColorMap size).
- newColorMap do:
- [:clr|
- ((newColors size < newColorMap size) and: [(newColors includes: clr) not])
- ifTrue:
- [
- newColors add: clr
- ]
- ].
- image colorMap: newColors.
- colorMapMode := aMode.
- (imageEditView image: image) notNil
- ifTrue:
- [
- self image fileName: oldFileName.
- self listOfColors contents: image colorMap.
- self findColorMapMode.
- self updateLabelsAndHistory.
- ]
-!
-
editMode: aMode
"returns whether editMode is equal to aMode"
@@ -1520,6 +1456,254 @@
"Modified: / 26.7.1998 / 12:32:55 / cg"
! !
+!ImageEditor methodsFor:'user actions - colormap'!
+
+colorMapMode:aMode value: aValue
+ "calculates a new color map for the image from aMode"
+
+ |depth numColors newColorMap newImage
+ oldImage image newColors realColorMap oldFileName
+ usedColors useNearest usageCounts tmpBits tmpMap|
+
+ self withExecuteCursorDo:[
+ oldImage := self image.
+
+ newColorMap := self class listOfColorMaps at:aMode.
+ depth := (newColorMap size log: 2) asInteger.
+
+ useNearest := false.
+ (self confirm:'Keep colormap (or use standard)') ifTrue:[
+ "/ keep the colormap
+ depth > oldImage depth ifTrue:[
+ "/ easy - simply copy the part
+ numColors := 1 bitShift:oldImage depth.
+ 0 to:numColors-1 do:[:pixel |
+ newColorMap at:(pixel+1) put:(oldImage colorFromValue:pixel)
+ ].
+ ] ifFalse:[
+ "/ see if all used color fit the new colormap
+ usedColors := oldImage usedColors.
+ usedColors := usedColors asArray.
+ usedColors size <= (1 bitShift:depth) ifTrue:[
+ "/ yea - just install them
+ usedColors keysAndValuesDo:[:idx :clr |
+ newColorMap at:idx put:clr
+ ]
+ ] ifFalse:[
+ "/ copy over those that are most often used.
+ oldImage depth ~~ 8 ifTrue:[
+ tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
+ oldImage bits
+ expandPixels:(oldImage depth)
+ width:oldImage width
+ height:oldImage height
+ into:tmpBits
+ mapping:nil.
+ ] ifFalse:[
+ tmpBits := oldImage bits
+ ].
+ usageCounts := tmpBits usageCounts.
+ tmpMap := Array new:usageCounts size.
+ oldImage colorMap asArray keysAndValuesDo:[:i :clr |
+ tmpMap at:i put:clr
+ ].
+ usageCounts sort:[:a :b | a > b] with:tmpMap.
+
+ 1 to:(1 bitShift:depth) do:[:idx |
+ newColorMap at:idx put:(tmpMap at:idx)
+ ].
+
+ useNearest := Dialog
+ confirmWithCancel:('Image requires %1 colors.\ColorMap has only space for %2\\Use nearest (or map to black) ?'
+ bindWith:usedColors size
+ with:(1 bitShift:depth)) withCRs
+ labels:#('cancel' 'black' 'nearest').
+ useNearest isNil ifTrue:[
+ ^ self "/ cancel
+ ].
+ ]
+ ]
+ ] ifFalse:[
+ "/ standard colormap
+ ].
+
+ imageEditView makeUndo.
+
+ newImage := (Image implementorForDepth: depth) new.
+ oldFileName := oldImage fileName.
+
+ Object errorSignal handle:
+ [:ex|
+ Object errorSignal handle:
+ [:ex|
+ imageEditView undo.
+ ^self warn: 'Conversion failed!!'
+ ]
+ do:
+ [
+ newImage := (Image implementorForDepth: depth) new.
+ newImage width:oldImage width height:oldImage height depth:depth.
+ newImage colorMap:newColorMap.
+ newImage photometric:#palette.
+ newImage bits:(ByteArray new:(newImage bytesPerRow * newImage height)).
+
+ oldImage colorsFromX:0 y:0 toX:(oldImage width-1) y:(oldImage height-1) do:
+ [:x :y :clr |
+ |newColor|
+
+ (newColorMap includes:clr)
+ ifTrue: [newColor := clr]
+ ifFalse: [
+ useNearest ifTrue:[
+ newColor := clr nearestIn:newColorMap
+ ] ifFalse:[
+ newColor := oldImage colorMap first
+ ]
+ ].
+ newImage colorAtX:x y:y put:newColor.
+ ].
+ image := newImage
+ ].
+ ]
+ do:
+ [
+ image := newImage fromImage: oldImage
+ ].
+
+ (String fromString: aMode) reverse readStream nextWord reverse = 'mask'
+ ifTrue:
+ [
+ image mask isNil
+ ifTrue:
+ [
+ image mask: (Depth1Image fromImage: (image asThresholdMonochromeImage: 0.1)).
+ ].
+ ]
+ ifFalse:
+ [
+ image mask: nil.
+ ].
+ realColorMap := OrderedCollection new.
+ image realColorMap do:
+ [:clr|
+ (realColorMap includes: clr) ifFalse: [realColorMap add: clr]
+ ].
+ newColors := realColorMap copyFrom: 1 to: (newColorMap size min: realColorMap size).
+ newColorMap do:
+ [:clr|
+ ((newColors size < newColorMap size) and: [(newColors includes: clr) not])
+ ifTrue:
+ [
+ newColors add: clr
+ ]
+ ].
+ image colorMap: newColors.
+ colorMapMode := aMode.
+
+ (imageEditView image: image) notNil ifTrue:
+ [
+ image fileName: oldFileName.
+ self listOfColors contents: image colorMap.
+ self findColorMapMode.
+ self updateLabelsAndHistory.
+ ]
+ ]
+
+ "Modified: / 28.7.1998 / 21:42:14 / cg"
+!
+
+compressColorMap
+ "calculates a new color map for the image, using only used colors"
+
+ |depth numColors newColorMap newImage
+ oldImage newColors realColorMap oldFileName
+ usedColors useNearest oldToNew oldBits newBits tmpBits|
+
+ oldImage := self image.
+ depth := oldImage depth.
+
+ oldImage photometric ~~ #palette ifTrue:[
+ self information:'Only palette images have colormaps.'.
+ ^ self
+ ].
+
+ usedColors := oldImage usedColors.
+ usedColors size == (1 bitShift:depth) ifTrue:[
+ self information:'All colors are used - no compression.'.
+ ^ self
+ ].
+ usedColors size == oldImage colorMap size ifTrue:[
+ self information:'Colormap already compressed - no compression.'.
+ ^ self
+ ].
+
+ imageEditView makeUndo.
+
+ self information:('%1 colors used.' bindWith:usedColors size).
+
+ self withExecuteCursorDo:[
+ newColorMap := Array new:usedColors size.
+
+ "/ translation table
+ oldToNew := ByteArray new:(1 bitShift:depth).
+ newColorMap := usedColors asArray.
+ oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
+ |newPixel|
+
+ (usedColors includes:clr) ifTrue:[
+ newPixel := newColorMap indexOf:clr.
+ oldToNew at:oldIdx put:newPixel-1.
+ ]
+ ].
+
+ oldBits := oldImage bits.
+ newBits := ByteArray new:(oldBits size).
+ depth ~~ 8 ifTrue:[
+ "/ expand/compress can only handle 8bits
+ tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
+ oldBits
+ expandPixels:depth
+ width:oldImage width
+ height:oldImage height
+ into:tmpBits
+ mapping:oldToNew.
+ tmpBits
+ compressPixels:depth
+ width:oldImage width
+ height:oldImage height
+ into:newBits
+ mapping:nil
+ ] ifFalse:[
+ oldBits
+ expandPixels:depth
+ width:oldImage width
+ height:oldImage height
+ into:newBits
+ mapping:oldToNew.
+ ].
+
+ newImage := oldImage species new
+ width:oldImage width
+ height:oldImage height
+ depth:depth
+ fromArray:newBits.
+
+ newImage colorMap:newColorMap.
+ newImage fileName:oldImage fileName.
+ newImage mask:(oldImage mask copy).
+
+ (imageEditView image:newImage) notNil ifTrue:
+ [
+ self listOfColors contents: newImage colorMap.
+ self findColorMapMode.
+ self updateLabelsAndHistory.
+ ]
+ ]
+
+ "Created: / 28.7.1998 / 20:03:11 / cg"
+ "Modified: / 28.7.1998 / 21:36:17 / cg"
+! !
+
!ImageEditor methodsFor:'user actions - editing'!
doBrowseClass