# HG changeset patch # User Claus Gittinger # Date 901655328 -7200 # Node ID 4e50c3164625e35c87bd3697fb71bf79d5f87747 # Parent 1172ecb3fd633410716e782acde0ce501fcd9ca9 more options (preserving colorMap) when changing the colorMapMode; added compressColormap function. diff -r 1172ecb3fd63 -r 4e50c3164625 ImageEditor.st --- 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