#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Thu, 23 Feb 2017 15:55:02 +0100
changeset 5499 8c729d93a77c
parent 5498 797c3e694be7
child 5500 821ec5a9d9c4
#FEATURE by cg class: ImageEditView class definition comment/format in: #drawingColors #drawingColors: #selectedColor #selectedColor: changed: #askForSpecialOperation #drawingColorHolders #gradientFillIn:orientation:auto: #initialize #makeUndo #undo
ImageEditView.st
--- a/ImageEditView.st	Thu Feb 23 14:22:56 2017 +0100
+++ b/ImageEditView.st	Thu Feb 23 15:55:02 2017 +0100
@@ -15,12 +15,13 @@
 
 ImageView subclass:#ImageEditView
 	instanceVariableNames:'readOnly magnification imageReaderClass resourceClass
-		resourceSelector mouseKeyColorMode undoImages modifiedHolder
-		editMode lastPastePoint imageInfoHolder activityInfoHolder
-		pickedColorHolder drawingColors drawingPixels drawingColorHolders
-		drawingPixelHolders clickInfoCallBack penWidth sprayProcess
-		sprayPosition spraySpot drawingAlpha floodFillMaxHueError
-		floodFillMaxLightError userAllowedToChangeDrawingColor'
+		resourceSelector mouseKeyColorMode undoImages originalImage
+		modifiedHolder editMode lastPastePoint imageInfoHolder
+		activityInfoHolder pickedColorHolder drawingColors drawingPixels
+		drawingColorHolders drawingPixelHolders clickInfoCallBack
+		penWidth sprayProcess sprayPosition spraySpot drawingAlpha
+		floodFillMaxHueError floodFillMaxLightError
+		userAllowedToChangeDrawingColor'
 	classVariableNames:'Clipboard ClipboardMagnified LastMagnification
 		GridMagnificationLimit MaxUndos LastSaveDirectory LastSaveClass
 		EditModePoint EditModeBox EditModeFilledBox EditModeFill
@@ -206,16 +207,25 @@
 !
 
 drawingColorHolders
+    drawingColorHolders isNil ifTrue:[
+        drawingColorHolders := Array with:(nil asValue) with:(nil asValue).   "/ left/right mouse colors
+    ].    
     ^ drawingColorHolders
+
+    "Modified: / 23-02-2017 / 10:14:49 / cg"
 !
 
 drawingColors
     ^ drawingColorHolders collect:[:each | each value].
+
+    "Modified: / 23-02-2017 / 10:17:14 / cg"
 !
 
 drawingColors:anArrayTwoColors
     (drawingColorHolders at:1) value:(anArrayTwoColors at:1).
     (drawingColorHolders at:2) value:(anArrayTwoColors at:2).
+
+    "Modified: / 23-02-2017 / 10:17:21 / cg"
 !
 
 editMode
@@ -449,11 +459,13 @@
     ].
     ^ clr
 
-    "Modified: / 20-09-2010 / 11:34:07 / cg"
+    "Modified: / 23-02-2017 / 10:17:06 / cg"
 !
 
 selectedColor: aColor
     (drawingColorHolders at:(mouseKeyColorMode min:drawingColorHolders size)) value:aColor
+
+    "Modified: / 23-02-2017 / 10:17:02 / cg"
 !
 
 selectedColorIndex
@@ -1032,11 +1044,13 @@
                ('-'                     nil nil)
                ('gradient fill horizontal'  fillHorizontalGradientRectIcon gradientFillHorizontal)
                ('gradient fill vertical'    fillVerticalGradientRectIcon gradientFillVertical)
-               ('gradient fill diagonal'    fillDiagonalGradientRectIcon gradientFillDiagonal)
+                "/ unfinished
+               "/ ('gradient fill diagonal'    fillDiagonalGradientRectIcon gradientFillDiagonal)
                ('-'                     nil nil) 
                ('auto gradient fill horizontal'  fillHorizontalGradientRectIcon autoGradientFillHorizontal)
                ('auto gradient fill vertical'    fillVerticalGradientRectIcon autoGradientFillVertical)
-               ('auto gradient fill diagonal'    fillDiagonalGradientRectIcon autoGradientFillDiagonal)
+                "/ unfinished
+               "/ ('auto gradient fill diagonal'    fillDiagonalGradientRectIcon autoGradientFillDiagonal)
              ).
     ].
     
@@ -1064,7 +1078,7 @@
     ^ operation
 
     "Created: / 20-02-2017 / 17:37:23 / cg"
-    "Modified: / 22-02-2017 / 21:02:02 / cg"
+    "Modified: / 23-02-2017 / 15:54:42 / cg"
 !
 
 autoCropLeft:doLeft right:doRight top:doTop bottom:doBottom
@@ -1341,12 +1355,13 @@
 !
 
 gradientFillIn:imageBox orientation:orientation auto:auto
-    "/ with auto, pick 2 (or 4 if diagonal) bounding pixels and do a gradient fill with those;
+    "/ with auto, pick 2 bounding pixels and do a gradient fill with those;
+    "/ (don't know what diagonal should do, yet)
     "/ if auto is false, use color1/color2 for the fill
 
     |x0 y0 x1 y1 image n color1 color2 
-     r0 g0 b0 dR dG dB i dist
-     cTop cBot xD yD cDiag n1 n2 dd|
+     r0 g0 b0 dR dG dB i cX cY A B qAB a b pD1x pD1y pD2x pD2y
+     dxH dyH hX hY dH dP f |
 
     self makeUndo.
 
@@ -1354,7 +1369,6 @@
     y0 := imageBox top.
     x1 := imageBox right-1.
     y1 := imageBox bottom-1.
-
     image := self image.
 
     self setModified.
@@ -1408,9 +1422,9 @@
         ^ self.
     ].
     
-    color1 := (drawingColorHolders at:1) value.
+    color1 := (self drawingColorHolders at:1) value.
     color1 isNil ifTrue:[ color1 := Color black ].
-    color2 := (drawingColorHolders at:2) value.
+    color2 := (self drawingColorHolders at:2) value.
     color2 isNil ifTrue:[ color2 := Color white ].
 
     r0 := color1 red.
@@ -1421,9 +1435,9 @@
         n := y1-y0.
         n = 0 ifTrue:[^ self].
         
-        dR := (color2 red - color1 red) / n.
-        dG := (color2 green - color1 green) / n.
-        dB := (color2 blue - color1 blue) / n.
+        dR := (color2 red - r0) / n.
+        dG := (color2 green - g0) / n.
+        dB := (color2 blue - b0) / n.
 
         x0 to:x1 do:[:x |
             i := 0.
@@ -1440,9 +1454,9 @@
         n := x1-x0.
         n = 0 ifTrue:[^ self ].
         
-        dR := (color2 red - color1 red) / n.
-        dG := (color2 green - color1 green) / n.
-        dB := (color2 blue - color1 blue) / n.
+        dR := (color2 red - r0) / n.
+        dG := (color2 green - g0) / n.
+        dB := (color2 blue - b0) / n.
 
         y0 to:y1 do:[:y |
             i := 1.
@@ -1457,50 +1471,164 @@
     ].
     
     orientation == #diagonal ifTrue:[
-        dist := ((x1 - x0) squared + (y1 - y0) squared) sqrt.
-        dR := (color2 red - color1 red) / dist.
-        dG := (color2 green - color1 green) / dist.
-        dB := (color2 blue - color1 blue) / dist.
+        cX := (x1+1 + x0) / 2.
+        cY := (y1+1 + y0) / 2.
+        A := cY-y0. 
+        B := cX-x0.
+        (A=0 or:[B=0]) ifTrue:[^ self].
+        
+        qAB := A/B.
         
-        x0 to:x1 do:[:x |
-            cTop := image colorAtX:x y:y0.
-            cBot := image colorAtX:x y:y1.
-            "/ point on diagonal
-            xD := x.
-            yD := (y1-y0)/(x1-x0)*x.
-            "/ color at point on diagonal
-            cDiag := image colorAtX:xD rounded y:yD rounded.
-            dd := ((x-x0) squared + (yD-y0) squared) sqrt.
-            cDiag := Color red:(color1 red + (dd*dR)) green:(color1 green + (dd*dG)) blue:(color1 blue + (dd*dB)).
-            
-            n1 := yD-y0+1. "/ num points between top at x and diagonalPoint at x
-            n2 := y1-yD+1. "/ num points between diagonalPoint at x and bottom at x and 
-            y0 to:y1 do:[:y |
-                |clr d dR2 dG2 dB2|
-
-                y < yD ifTrue:[
-                    "/ gradient from top-color at x to diagonal point at x
-                    d := y-y0.
-                    dR2 := (cDiag red - cTop red) / n1.
-                    dG2 := (cDiag green - cTop green) / n1.
-                    dB2 := (cDiag blue - cTop blue) / n1.
-                    clr := Color red:(cTop red + (d*dR2)) green:(cTop green + (d*dG2)) blue:(cTop blue + (d*dB2)).
+        "/ {(cX-10) rounded . (cX-5) rounded . cX rounded . (cX+5)rounded . (cX+10)rounded } 
+        x0 to:x1 
+        do:[:x |
+            b := cX-x.
+            b = 0 ifTrue:[
+                pD1x := pD2x := cX.
+                pD1y := pD2y := cY.
+            ] ifFalse:[    
+                "/ (A/B) = (a/b) -> a = (A/B)*b
+                a := qAB*b.
+                pD1x := ((cX-b) max:x0) min:x1. 
+                pD1y := ((cY+a) max:y0) min:y1. 
+                pD2x := ((cX-b) max:x0) min:x1. 
+                pD2y := ((cY-a) max:y0) min:y1.  
+            ].
+            "/ {(cY-10)rounded . (cY-5)rounded . cY rounded. (cY+5)rounded. (cY+10)rounded } 
+            y0 to:y1 
+            do:[:y |
+                "/ the edge-point to interpolate against...
+                "/ take a line from C through x/y and compute where it hits the edge H
+                a := y-cY.
+                b := x-cX.
+                (a = 0) ifTrue:[
+                    "/ exactly in the middle
+                    hX := (x < cX) ifTrue:[x0] ifFalse:[x1].
+                    hY := cY.
                 ] ifFalse:[    
-                    "/ gradient from diagonal point at x to bottom point at x
-                    d := y1-y.
-                    dR2 := (cBot red - cDiag red) / n2.
-                    dG2 := (cBot green - cDiag green) / n2.
-                    dB2 := (cBot blue - cDiag blue) / n2.
-                    clr := Color red:(cDiag red + (d*dR2)) green:(cDiag green + (d*dG2)) blue:(cDiag blue + (d*dB2)).
+                    (b = 0) ifTrue:[
+                        hX := cX.
+                        hY := (y < cY) ifTrue:[y0] ifFalse:[y1].
+                    ] ifFalse:[    
+                        "/ (dH/A) = (b/a) -> dH = (b/a)*A
+                        y <= pD1y ifTrue:[
+                            "/ in left-upper half
+                            (y <= pD2y) ifTrue:[
+                                "/ in upper quadrant
+                                dxH := (b/a)*A.
+                                hX := cX-dxH.
+                                hY := y0.
+                            ] ifFalse:[
+                                "/ in left quadrant
+                                dyH := (a/b)*B negated.
+                                hY := cY+dyH.
+                                hX := x0.
+                            ].    
+                        ] ifFalse:[
+                            "/ in right-lower half
+                            y >= pD2y ifTrue:[
+                                "/ in lower quadrant 
+                                dxH := (b/a)*A negated.
+                                hX := cX-dxH.
+                                hY := y1.
+                            ] ifFalse:[
+                                "/ in right quadrant
+                                dyH := (a/b)*B.
+                                hY := cY+dyH.
+                                hX := x1.
+                            ].
+                        ].
+                    ].
+                    hX := hX min:x1.
+                    hY := hY min:y1.
                 ].
-                image colorAtX:x y:y put:clr.
-            ]
+
+                "/ the color at H
+                color2 := image colorAtX:hX rounded y:hY rounded.
+
+                "/ the distance between H and C
+                dH := (hX@hY) dist:(cX@cY).
+                "/ the distance between P and C
+                dP := (x@y) dist:(cX@cY).
+                "/ the fraction (0 at H; 1 at C) 
+                f := 1 - (dP / dH).
+                self assert:(f between:0 and:1).
+                
+                "/ the new color
+                dR := color2 red + ((r0-color2 red ) * f).
+                dG := color2 green + ((g0-color2 green) * f).
+                dB := color2 blue + ((b0-color2 blue) * f).
+                image colorAtX:x y:y put:(Color red:dR green:dG blue:dB).
+                
+"/                y <= pD1y ifTrue:[
+"/                    "/ in left-upper half
+"/                    (y <= pD2y) ifTrue:[
+"/                        "/ in upper quadrant
+"/                        image colorAtX:x y:y put:Color red.
+"/                    ] ifFalse:[
+"/                        "/ in left quadrant
+"/                        image colorAtX:x y:y put:Color green.
+"/                    ].    
+"/                ] ifFalse:[
+"/                    "/ in right-lower half
+"/                    y >= pD2y ifTrue:[
+"/                        "/ in lower quadrant 
+"/                        image colorAtX:x y:y put:Color blue.
+"/                    ] ifFalse:[
+"/                        "/ in right quadrant 
+"/                        image colorAtX:x y:y put:Color yellow.
+"/                    ].
+"/                    
+"/                ].
+            ].
         ].
+        "/ image colorAtX:cX rounded y:cY rounded put:Color magenta.
+
+"/            clr2 := image colorAtX:p2X y:p2Y.
+"/            
+"/            cTop := image colorAtX:x y:y0.
+"/            cBot := image colorAtX:x y:y1.
+"/            "/ point on diagonal
+"/            xD := x.
+"/            yD := (y1-y0)/(x1-x0)*x.
+"/            "/ color at point on diagonal
+"/            "/ cDiag := image colorAtX:xD rounded y:yD rounded.
+"/            "/ the distance of the diagonal point from the origin
+"/            dd := ((x-x0) squared + (yD-y0) squared) sqrt.
+"/            "/ desired color at point on diagonal
+"/            cDiag := Color red:(color1 red + (dd*dR)) green:(color1 green + (dd*dG)) blue:(color1 blue + (dd*dB)).
+"/"/ image colorAtX:xD rounded y:yD rounded put:cDiag.
+"/            
+"/            n1 := yD-y0+1. "/ num points between top at x and diagonalPoint at x
+"/            n2 := y1-yD+1. "/ num points between diagonalPoint at x and bottom at x 
+"/            y0 to:y1 do:[:y |
+"/                |clr d dR2 dG2 dB2|
+"/
+"/                y < yD ifTrue:[
+"/                    "/ gradient from top-color at x to diagonal point at x
+"/                    d := y-y0.
+"/                    dR2 := (cDiag red - cTop red) / n1.
+"/                    dG2 := (cDiag green - cTop green) / n1.
+"/                    dB2 := (cDiag blue - cTop blue) / n1.
+"/                    clr := Color red:(cTop red + (d*dR2)) green:(cTop green + (d*dG2)) blue:(cTop blue + (d*dB2)).
+"/                image colorAtX:x y:y put:clr.
+"/                ] ifFalse:[    
+"/                    "/ gradient from diagonal point at x to bottom point at x
+"/                    d := y-yD.
+"/                    dR2 := (cBot red - cDiag red) / n2.
+"/                    dG2 := (cBot green - cDiag green) / n2.
+"/                    dB2 := (cBot blue - cDiag blue) / n2.
+"/                    clr := Color red:(cDiag red + (d*dR2)) green:(cDiag green + (d*dG2)) blue:(cDiag blue + (d*dB2)).
+"/                    "/ clr := image colorAtX:x y:y.
+"/                image colorAtX:x y:y put:clr.
+"/                ].
+"/            ]
+"/        ].
         ^ self.
     ].
 
     "Created: / 22-02-2017 / 21:00:01 / cg"
-    "Modified: / 22-02-2017 / 23:05:49 / cg"
+    "Modified: / 23-02-2017 / 15:41:23 / cg"
 !
 
 magnifyAntiAliasedImageTo:newSize
@@ -1623,14 +1751,18 @@
 !
 
 makeUndo
-    image notNil ifTrue:[       
+    |theCopy|
+    
+    image notNil ifTrue:[        
         [undoImages size >= MaxUndos] whileTrue:[
             undoImages removeFirst.
         ].
-        undoImages add:image copy
+        theCopy := image copy.
+        undoImages add:theCopy.
+        originalImage isNil ifTrue:[ originalImage := theCopy ].
     ]
 
-    "Modified: / 20-11-2007 / 17:26:50 / cg"
+    "Modified: / 23-02-2017 / 15:43:55 / cg"
 !
 
 pasteAt: aPoint mode:modeSymbol
@@ -2039,19 +2171,25 @@
 !
 
 undo
-    undoImages notEmpty ifTrue:[           
-        windowGroup withExecuteCursorDo:[
-            |oldImage newImage|
-            
-            oldImage := self image.
-            newImage := undoImages removeLast.
-            self clearModified.
-            self image:newImage scroll:(newImage extent ~= oldImage extent) "false".
-            "/ self changed:#image.
-        ]
+    |newImage|
+    
+    undoImages notEmpty ifTrue:[
+        newImage := undoImages removeLast.
+    ] ifFalse:[
+        (Dialog confirm:(resources string:'No more undo images remembered. Back to the initial image?'))
+            ifFalse:[^ self].
+        newImage := originalImage copy
+    ].
+    
+    windowGroup withExecuteCursorDo:[
+        |oldImage|
+
+        oldImage := self image.
+        self clearModified.
+        self image:newImage scroll:(newImage extent ~= oldImage extent).
     ]
 
-    "Modified: / 10.2.2000 / 23:21:24 / cg"
+    "Modified: / 23-02-2017 / 15:47:15 / cg"
 ! !
 
 !ImageEditView methodsFor:'image editing-editmode button actions'!
@@ -3088,7 +3226,9 @@
     modifiedHolder    := false asValue.
     mouseKeyColorMode := 1.
     resourceClass     := resourceSelector := nil.
-    drawingColorHolders := Array with:(nil asValue) with:(nil asValue).   "/ left/right mouse colors
+    drawingColorHolders isNil ifTrue:[
+        drawingColorHolders := Array with:(nil asValue) with:(nil asValue).   "/ left/right mouse colors
+    ].
     drawingPixelHolders := Array with:(nil asValue) with:(nil asValue).   "/ left/right mouse colors
 
     spraySpot := 8.
@@ -3098,7 +3238,7 @@
     
     self editMode:EditModePoint.
 
-    "Modified: / 17-02-2017 / 16:24:04 / cg"
+    "Modified: / 23-02-2017 / 10:17:46 / cg"
 ! !
 
 !ImageEditView methodsFor:'loading & saving'!