--- a/Color.st Tue Aug 29 20:08:35 2017 +0200
+++ b/Color.st Tue Aug 29 21:59:53 2017 +0200
@@ -3550,9 +3550,9 @@
best:numColors ditherColorsForImage:anImage
"work in progress"
- |bigCube boxMax numBits numGray usedColors
+ |cube boxMaxR boxMaxG boxMaxB numBitsR numBitsG numBitsB numGray usedColors
minRed maxRed minGreen maxGreen minBlue maxBlue
- boundaryColors boxesSegmented segments boxesToDo enumerateNeighbors
+ boundaryColors boxesAlreadySegmented segments boxesToDo enumerateNeighbors
firstTry segmentColors|
((anImage photometric == #blackIs0) or:[anImage photometric == #whiteIs0]) ifTrue:[
@@ -3567,13 +3567,18 @@
].
].
- boxMax := 63.
- numBits := 6.
+ numBitsR := 7.
+ numBitsG := 8.
+ numBitsB := 5.
+
firstTry := true.
[
- "/ first, a rough cube with less precision...
- bigCube := IntegerArray new:(boxMax+1)*(boxMax+1)*(boxMax+1).
+ boxMaxR := (1 << numBitsR) - 1.
+ boxMaxG := (1 << numBitsG) - 1.
+ boxMaxB := (1 << numBitsB) - 1.
+
+ cube := IntegerArray new:(boxMaxR+1)*(boxMaxG+1)*(boxMaxB+1).
firstTry ifTrue:[
usedColors := Set new.
@@ -3591,11 +3596,11 @@
greenByte := (rgb rightShift:8) bitAnd:16rFF.
blueByte := (rgb) bitAnd:16rFF.
- r := redByte rightShift:(8-numBits).
- g := greenByte rightShift:(8-numBits).
- b := blueByte rightShift:(8-numBits).
- idx := (((r * (boxMax+1))+g)*(boxMax+1))+b+1.
- oldCount := bigCube at:idx.
+ r := redByte rightShift:(8-numBitsR).
+ g := greenByte rightShift:(8-numBitsG).
+ b := blueByte rightShift:(8-numBitsB).
+ idx := (((r * (boxMaxG+1))+g)*(boxMaxB+1))+b+1.
+ oldCount := cube at:idx.
firstTry ifTrue:[
redByte < minRed ifTrue:[minRed := redByte] ifFalse:[redByte > maxRed ifTrue:[maxRed := redByte]].
@@ -3606,7 +3611,7 @@
usedColors add:rgb.
].
].
- bigCube at:idx put:oldCount+1.
+ cube at:idx put:oldCount+1.
].
firstTry ifTrue:[
@@ -3642,7 +3647,7 @@
"/
"/ find and generate connected subarea box sets
"/
- boxesSegmented := Set new.
+ boxesAlreadySegmented := Set new.
segments := OrderedCollection new.
boxesToDo := OrderedCollection new.
@@ -3653,17 +3658,17 @@
[:rgb :aBlock|
|r g b|
- r := (rgb rightShift:(numBits+numBits)) bitAnd:boxMax.
- g := (rgb rightShift:numBits) bitAnd:boxMax.
- b := (rgb) bitAnd:boxMax.
+ r := (rgb rightShift:(numBitsG+numBitsB)) bitAnd:boxMaxR.
+ g := (rgb rightShift:numBitsB) bitAnd:boxMaxG.
+ b := (rgb) bitAnd:boxMaxB.
r-1 to:r+1 do:[:n_r |
- (n_r between:0 and:boxMax) ifTrue:[
+ (n_r between:0 and:boxMaxR) ifTrue:[
g-1 to:g+1 do:[:n_g |
- (n_g between:0 and:boxMax) ifTrue:[
+ (n_g between:0 and:boxMaxG) ifTrue:[
b-1 to:b+1 do:[:n_b |
- (n_b between:0 and:boxMax) ifTrue:[
+ (n_b between:0 and:boxMaxB) ifTrue:[
((n_r == r) and:[n_g == g and:[n_b == b]]) ifFalse:[
- aBlock value:((((n_r * (boxMax+1))+n_g)*(boxMax+1))+n_b).
+ aBlock value:((((n_r * (boxMaxG+1))+n_g)*(boxMaxB+1))+n_b).
]
]
]
@@ -3673,14 +3678,14 @@
].
].
- 0 to:boxMax do:[:r |
- 0 to:boxMax do:[:g |
- 0 to:boxMax do:[:b |
+ 0 to:boxMaxR do:[:r |
+ 0 to:boxMaxG do:[:g |
+ 0 to:boxMaxB do:[:b |
|rgb|
- rgb := (((r * (boxMax+1))+g)*(boxMax+1))+b.
- (bigCube at:rgb+1) ~~ 0 ifTrue:[
- (boxesSegmented includes:rgb) ifFalse:[
+ rgb := (((r * (boxMaxG+1))+g)*(boxMaxB+1))+b.
+ (cube at:rgb+1) ~~ 0 ifTrue:[
+ (boxesAlreadySegmented includes:rgb) ifFalse:[
|currentSegment|
"/ start a segment
@@ -3688,7 +3693,7 @@
segments add:currentSegment.
boxesToDo add:rgb.
- boxesSegmented add:rgb.
+ boxesAlreadySegmented add:rgb.
[boxesToDo notEmpty] whileTrue:[
|rgb|
@@ -3697,11 +3702,11 @@
currentSegment add:rgb.
enumerateNeighbors value:rgb value:[:n_rgb |
- (bigCube at:n_rgb+1) ~~ 0 ifTrue:[
+ (cube at:n_rgb+1) ~~ 0 ifTrue:[
"/ neighbor has used pixels as well...
- (boxesSegmented includes:n_rgb) ifFalse:[
+ (boxesAlreadySegmented includes:n_rgb) ifFalse:[
"/ neighbor was not processed...
- boxesSegmented add:rgb.
+ boxesAlreadySegmented add:rgb.
boxesToDo add:n_rgb.
].
].
@@ -3727,28 +3732,29 @@
eachSegment do:[:rgbOfBoxInSegment |
|r g b idx count|
- r := (rgbOfBoxInSegment rightShift:(numBits+numBits)) bitAnd:boxMax.
- g := (rgbOfBoxInSegment rightShift:numBits) bitAnd:boxMax.
- b := (rgbOfBoxInSegment) bitAnd:boxMax.
-
- idx := (((r * (boxMax+1))+g)*(boxMax+1))+b+1.
- count := bigCube at:idx.
-
- sumRed := sumRed + r.
- sumGreen := sumGreen + g.
- sumBlue := sumBlue + b.
+ r := (rgbOfBoxInSegment rightShift:(numBitsG+numBitsB)) bitAnd:boxMaxR.
+ g := (rgbOfBoxInSegment rightShift:numBitsB) bitAnd:boxMaxG.
+ b := (rgbOfBoxInSegment) bitAnd:boxMaxB.
+
+ idx := (((r * (boxMaxG+1))+g)*(boxMaxB+1))+b+1.
+ count := cube at:idx.
+
+ sumRed := sumRed + (r * count).
+ sumGreen := sumGreen + (g * count).
+ sumBlue := sumBlue + (b * count).
+
sumWeight := sumWeight + count.
].
centerRed := (sumRed / sumWeight) rounded.
centerGreen := (sumGreen / sumWeight) rounded.
centerBlue := (sumBlue / sumWeight) rounded.
- centerRed := (centerRed bitShift:(8-numBits))
- bitOr:(centerRed bitShift:(8-numBits-numBits)).
- centerGreen := (centerGreen bitShift:(8-numBits))
- bitOr:(centerGreen bitShift:(8-numBits-numBits)).
- centerBlue := (centerBlue bitShift:(8-numBits))
- bitOr:(centerBlue bitShift:(8-numBits-numBits)).
+ centerRed := (centerRed bitShift:(8-numBitsR))
+ bitOr:(centerRed bitShift:(8-numBitsR-numBitsR)).
+ centerGreen := (centerGreen bitShift:(8-numBitsG))
+ bitOr:(centerGreen bitShift:(8-numBitsG-numBitsG)).
+ centerBlue := (centerBlue bitShift:(8-numBitsB))
+ bitOr:(centerBlue bitShift:(8-numBitsB-numBitsB)).
Color redByte:centerRed greenByte:centerGreen blueByte:centerBlue.
]
@@ -3771,10 +3777,11 @@
^ segmentColors.
].
- numBits := numBits - 1.
- boxMax := ((boxMax+1) // 2) - 1.
+ numBitsR > 2 ifTrue:[ numBitsR := numBitsR - 1 ].
+ numBitsG > 2 ifTrue:[ numBitsG := numBitsG - 1 ].
+ numBitsB > 2 ifTrue:[ numBitsB := numBitsB - 1 ].
- numBits == 0 ifTrue:[
+ ((numBitsR == 0) or:[numBitsG == 0 or:[numBitsB == 0]]) ifTrue:[
self error.
].
] loop.
@@ -3795,7 +3802,7 @@
"
"Created: / 29-08-2017 / 14:31:19 / cg"
- "Modified: / 29-08-2017 / 20:04:36 / cg"
+ "Modified: / 29-08-2017 / 21:53:47 / cg"
!
browserColors