# HG changeset patch # User sr # Date 1216653280 -7200 # Node ID 2ed2f4e7931e047a34211ce97422078d5a860054 # Parent 15d53562d4e80f4e37a56851d3bb06891493cdd7 *** empty log message *** diff -r 15d53562d4e8 -r 2ed2f4e7931e Image.st --- a/Image.st Wed Jul 16 12:47:11 2008 +0200 +++ b/Image.st Mon Jul 21 17:14:40 2008 +0200 @@ -15,7 +15,8 @@ instanceVariableNames:'pixelStore bytes width height bitsPerPixel depth colorMap maxPixelValue rowByteSize bitsPerSample samplesPerPixel photometric device deviceForm monoDeviceForm fullColorDeviceForm - mask maskedPixelsAre0 fileName imageSequence' + mask maskedPixelsAre0 fileName imageSequence aaBlendWithStart + aaDictionary' classVariableNames:'Lobby DitherAlgorithm NumberOfDitherColors CollectGarbageWhenRunningOutOfColors ImageErrorSignal ImageNotFoundQuerySignal BadImageFormatQuerySignal @@ -769,6 +770,64 @@ ^ self width:ext x height:ext y depth:d ! +extent:ext depth:d antiAliasedPalette:aBasicColorArray bgColor:bgColor + ^ self extent:ext depth:d antiAliasedPalette:aBasicColorArray bgColor:bgColor mixedArray:#(1.0 0.8 0.6 0.4 0.2) + + " + |colorMap i| + + colorMap := Array with:Color white with:Color blue. + + i := Depth8Image extent:300@400 depth:8 antiAliasedPalette:colorMap bgColor:Color white. + i fillAntiAliasedArc:200@200 radius:80 from:0 angle:360 withColor:Color blue. + i inspect. + " +! + +extent:ext depth:d antiAliasedPalette:aBasicColorArray bgColor:bgColor mixedArray:mixedArray + |colors colorMap colorIndex colorDictionary tmpDic newImage emptyBits| + + colors := OrderedCollection new. + colorMap := OrderedCollection new. + colorIndex := 0. + colorDictionary := Dictionary new. + + aBasicColorArray do:[:aColor | + colorMap add:aColor. + colorIndex := colorIndex + 1. + + tmpDic := Dictionary new. + + mixedArray do:[:aFloat | + tmpDic at:aFloat put:colorIndex. + colorMap add:(aColor mixed:aFloat with:bgColor). + colorIndex := colorIndex + 1. + ]. + + colorDictionary at:aColor put:tmpDic. + ]. + + newImage := (self implementorForDepth:d) new. + newImage aaDictionary:colorDictionary. + newImage aaBlendWithStart:mixedArray first. + + newImage width:ext x height:ext y depth:d palette:colorMap. + emptyBits := ByteArray new:(newImage bytesPerRow * ext y). + newImage bits:emptyBits. + + ^ newImage + + " + |colorMap i| + + colorMap := Array with:Color white with:Color blue. + + i := Depth8Image extent:300@400 depth:8 antiAliasedPalette:colorMap bgColor:Color white. + i fillAntiAliasedArc:200@200 radius:80 from:0 angle:360 withColor:Color blue. + i inspect. + " +! + extent:ext depth:d bits:bits "ST-80 compatibility; assume 32-bit padding" @@ -2215,6 +2274,14 @@ !Image methodsFor:'accessing'! +aaBlendWithStart:something + aaBlendWithStart := something. +! + +aaDictionary:something + aaDictionary := something. +! + bitsPerSample "return the number of bits per sample. The return value is an array of bits-per-plane." @@ -3228,7 +3295,6 @@ "Created: 20.6.1996 / 17:09:53 / cg" ! ! - !Image methodsFor:'conversion helpers'! rgbColormapFor:aDevice @@ -8649,7 +8715,56 @@ " ! -fillArc:origin radius:r from:startAngle angle:angle withColor:aColorOrIndex +fillAntiAliasedArc:origin radius:r from:startAngle angle:angle withColor:aColor + "draw a circle with some pixel value. + By using a tempForm, we assure that the same pixel algorithm is used as in a window" + + |tempForm wI "{ Class: SmallInteger }" + hI "{ Class: SmallInteger }" + colorValue| + + self assert:(aaBlendWithStart notNil). + self assert:(aaDictionary notNil). + + wI := self width. + hI := self height. + + tempForm := Form width:wI height:hI depth:1 onDevice:Screen current. + tempForm clear. + tempForm paint:(Color colorId:1). + tempForm fillArc:origin radius:r from:startAngle angle:angle. + + colorValue := self valueFromColor:aColor. + + 0 to:hI-1 do:[:yRun| + 0 to:wI-1 do:[:xRun| + (tempForm atX:xRun y:yRun) == 1 ifTrue:[ + self atImageAndMask:(xRun)@(yRun) putValue:colorValue. + + #(#left right) do:[:aHorizontal | + #(#top bottom) do:[:aVertical | + self vitualAntiAliasedAlongXvertical:aVertical horizontal:aHorizontal form:tempForm color:aColor xRun:xRun yRun:yRun. + self vitualAntiAliasedAlongYhorizontal:aHorizontal vertical:aVertical form:tempForm color:aColor xRun:xRun yRun:yRun. + ]. + ]. + ]. + ]. + ]. + + " + |cm i| + + cm := Array with:Color white with:Color black with:Color red with:Color blue. + + i := Depth8Image extent:300@400 depth:8 antiAliasedPalette:cm bgColor:Color white. + i fillAntiAliasedArc:205@195 radius:80 from:0 angle:90 withColor:Color red. + i fillAntiAliasedArc:200@200 radius:80 from:90 angle:270 withColor:Color blue. + i inspect. + + " +! + +fillArc:origin radius:r from:startAngle angle:angle withColor:aColorOrIndex "draw a circle with some pixel value. By using a tempForm, we assure that the same pixel algorithm is used as in a window" @@ -11167,7 +11282,6 @@ self photometric:(self class defaultPhotometric) ! ! - !Image methodsFor:'instance release'! close @@ -13468,10 +13582,160 @@ "Modified: 11.7.1996 / 11:11:34 / cg" ! ! +!Image methodsFor:'virtual anti-aliased'! + +vitualAntiAliasedAlongXvertical:bottomOrTop horizontal:leftOrRight form:tempForm color:aColor xRun:xRun yRun:yRun + |isBottom isLeft additionalY workPoint startX endX pixels pixelPos percent distance nearestKey tmp| + + self assert:(aaBlendWithStart notNil). + self assert:(aaDictionary notNil). + + isBottom := bottomOrTop sameAs:'bottom'. + isBottom ifTrue:[ + additionalY := -1. + ] ifFalse:[ + additionalY := 1. + ]. + + isLeft := leftOrRight sameAs:'left'. + isLeft ifTrue:[ + workPoint := (xRun - 1)@yRun. + [( + (tempForm atX:workPoint x y:workPoint y) == 0 and:[ + (tempForm atX:workPoint x y:workPoint y + additionalY) == 1]) and:[ + (tempForm atX:workPoint x - 1 y:workPoint y + additionalY) == 1] + ] whileTrue:[ + startX := workPoint x. + endX isNil ifTrue:[endX := workPoint x]. + workPoint := (workPoint x - 1)@yRun. + ]. + ] ifFalse:[ + workPoint := (xRun + 1)@yRun. + [( + (tempForm atX:workPoint x y:workPoint y) == 0 and:[ + (tempForm atX:workPoint x y:workPoint y + additionalY) == 1]) and:[ + (tempForm atX:workPoint x + 1 y:workPoint y + additionalY) == 1] + ] whileTrue:[ + endX := workPoint x. + startX isNil ifTrue:[startX := workPoint x]. + workPoint := (workPoint x + 1)@yRun. + ]. + ]. + + (startX notNil and:[endX notNil]) ifTrue:[ + startX = endX ifTrue:[ + self atImageAndMask:startX@yRun putValue:((aaDictionary at:aColor) at:aaBlendWithStart). + ] ifFalse:[ + pixels := (endX - startX) + 1. + startX to:endX do:[:x | + isLeft ifTrue:[ + pixelPos := (x - startX) + 1. + ] ifFalse:[ + pixelPos := (endX - x) + 1. + ]. + + percent := (100 / (pixels / pixelPos)) asFloat / 100. + + (aaDictionary at:aColor) keys do:[:aKey | + nearestKey isNil ifTrue:[ + distance := percent dist:aKey. + nearestKey := aKey. + ] ifFalse:[ + tmp := percent dist:aKey. + distance > tmp ifTrue:[ + distance := tmp. + nearestKey := aKey. + ]. + ]. + ]. + + self atImageAndMask:x@yRun putValue:((aaDictionary at:aColor) at:nearestKey). + + distance := nil. + nearestKey := nil. + ]. + ]. + ]. +! + +vitualAntiAliasedAlongYhorizontal:leftOrRight vertical:bottomOrTop form:tempForm color:aColor xRun:xRun yRun:yRun + |isLeft isBottom additionalX workPoint startY endY pixels pixelPos percent distance nearestKey tmp| + + self assert:(aaBlendWithStart notNil). + self assert:(aaDictionary notNil). + + isLeft := leftOrRight sameAs:'left'. + isLeft ifTrue:[ + additionalX := 1. + ] ifFalse:[ + additionalX := -1. + ]. + + isBottom := bottomOrTop sameAs:'bottom'. + isBottom ifTrue:[ + workPoint := xRun@(yRun + 1). + [( + (tempForm atX:workPoint x y:workPoint y) == 0 and:[ + (tempForm atX:workPoint x + additionalX y:workPoint y) == 1]) and:[ + (tempForm atX:workPoint x + additionalX y:workPoint y + 1) == 1] + ] whileTrue:[ + endY := workPoint y. + startY isNil ifTrue:[startY := workPoint y]. + workPoint := xRun@(workPoint y + 1). + ]. + ] ifFalse:[ + workPoint := xRun@(yRun - 1). + [( + (tempForm atX:workPoint x y:workPoint y) == 0 and:[ + (tempForm atX:workPoint x + additionalX y:workPoint y) == 1]) and:[ + (tempForm atX:workPoint x + additionalX y:workPoint y - 1) == 1] + ] whileTrue:[ + startY := workPoint y. + endY isNil ifTrue:[endY := workPoint y]. + workPoint := xRun@(workPoint y - 1). + ]. + ]. + + (startY notNil and:[endY notNil]) ifTrue:[ + startY = endY ifTrue:[ + self atImageAndMask:xRun@startY putValue:((aaDictionary at:aColor) at:aaBlendWithStart). + ] ifFalse:[ + pixels := (endY - startY) + 1. + startY to:endY do:[:y | + isBottom ifTrue:[ + pixelPos := (endY - y) + 1. + ] ifFalse:[ + pixelPos := (y - startY) + 1. + ]. + + percent := (100 / (pixels / pixelPos)) asFloat / 100. + + (aaDictionary at:aColor) keys do:[:aKey | + nearestKey isNil ifTrue:[ + distance := percent dist:aKey. + nearestKey := aKey. + ] ifFalse:[ + tmp := percent dist:aKey. + distance > tmp ifTrue:[ + distance := tmp. + nearestKey := aKey. + ]. + ]. + ]. + + self atImageAndMask:xRun@y putValue:((aaDictionary at:aColor) at:nearestKey). + + distance := nil. + nearestKey := nil. + ]. + ]. + ]. +! ! + !Image class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.410 2008-07-16 10:47:11 sr Exp $' + ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.411 2008-07-21 15:14:40 sr Exp $' ! ! Image initialize!