ReduceImageColors()
Verfasst: 12.08.2005 10:57
Ahoi.
Folgender Code reduziert die Anzahl Farben eines Bildes auf 2-16 Farben.
Ihm liegt allerdings kein bekannter+bewährter Algorithmus zugrunde, sondern ist lediglich auf meinen eigenen Mist gewachsen, aber immerhin tut er einigermaßen das, was er soll.
Ahoi,
Froggerprogger
Folgender Code reduziert die Anzahl Farben eines Bildes auf 2-16 Farben.
Ihm liegt allerdings kein bekannter+bewährter Algorithmus zugrunde, sondern ist lediglich auf meinen eigenen Mist gewachsen, aber immerhin tut er einigermaßen das, was er soll.
Ahoi,
Froggerprogger
Code: Alles auswählen
;- ReduceImageColors() v1.0
;- Reduces the number of colors of an image to 2-16 colors
;- and finds adequate colors for that.
;- Returns a new created copy containing the reduced image.
;- The algorithm will not be the best out there (was just
;- based on some simple thoughts), but it works!
;-
;- 12.08.05 by Froggerprogger
Structure RGBCountElement
red.l
green.l
blue.l
count.l
EndStructure
Dim InputImage.l(0,0)
Dim ImageColors4096.RGBCountElement(4095)
Dim OutputColors.RGBCountElement(0)
Procedure ReduceImageColors(imageNumber.l, numColors.l) ; Reduces the number of colors to 1 - 16 colors. Returns the new image.
If numColors < 2 Or numColors > 16 Or IsImage(imageNumber) = 0
ProcedureReturn 0
EndIf
Protected width.l, height.l, color.l, red.l, green.l, blue.l, index.l
Protected currentMaximumPos.l
Protected i.l, j.l, k.l, l.l, m.l
UseImage(imageNumber)
width = ImageWidth()
height = ImageHeight()
Dim InputImage.l(width-1, height-1)
StartDrawing(ImageOutput())
For i=0 To width-1
For j=0 To height-1
color = Point(i,j)
; 'copy' the image to an array
InputImage(i,j) = color
;count the color-hits
red = Int(Red(color) / 16)
green = Int(Green(color) / 16)
blue = Int(Blue(color) / 16)
index = red + green << 4 + blue << 8
ImageColors4096(index)\count + 1
Next
Next
StopDrawing()
Dim OutputColors.RGBCountElement(numColors-1)
For i=0 To numColors-1
currentMaximumPos = 0
; get the most often value
For j=1 To 4095
If ImageColors4096(j)\count > ImageColors4096(currentMaximumPos)\count
currentMaximumPos = j
EndIf
Next
OutputColors(i)\red = currentMaximumPos & $F
OutputColors(i)\green = (currentMaximumPos >> 4) & $F
OutputColors(i)\blue = (currentMaximumPos >> 8) & $F
; remove entries that are closest to the current outputcolor
removeNum = 1 + width * height / numColors
removed = 0
ignoreTheseWays = 0
For j=0 To 15
For k=0 To 15
For l=0 To 15
For m=0 To 7
; bitfield used for speeding up
If ignoreTheseWays & (1 << m)
Continue
EndIf
If m & %1
red = OutputColors(i)\red + j
If red > 15
Continue
EndIf
Else
red = OutputColors(i)\red - j
If red < 0
Continue
EndIf
EndIf
If m & %10
green = OutputColors(i)\green + k
If green > 15
Continue
EndIf
Else
green = OutputColors(i)\green - k
If green < 0
Continue
EndIf
EndIf
If m & %100
blue = OutputColors(i)\blue + l
If blue > 15
Continue
EndIf
Else
blue = OutputColors(i)\blue - l
If blue < 0
Continue
EndIf
EndIf
index = red + green << 4 + blue << 8
If ImageColors4096(index)\count = -1
ignoreTheseWays = ignoreTheseWays | (1 << m)
If ignoreTheseWays = %11111111
Break 4
EndIf
EndIf
removed = removed + ImageColors4096(index)\count
ImageColors4096(index)\count = -1
ImageColors4096(index)\red = red
ImageColors4096(index)\green = green
ImageColors4096(index)\blue = blue
If totalremoved + removed >= width * height
Break 5
EndIf
If removed >= removeNum
Break 4
EndIf
Next
Next
Next
Next
totalremoved + removed
Next
outputimage = CreateImage(#PB_Any, width, height)
StartDrawing(ImageOutput())
For i=0 To width-1
For j=0 To height-1
color = InputImage(i,j)
red = Int(Red(color) / 16)
green = Int(Green(color) / 16)
blue = Int(Blue(color) / 16)
minindex = 0
minval = Abs(red - OutputColors(0)\red) + Abs(green - OutputColors(0)\green) + Abs(blue - OutputColors(0)\blue)
For k=1 To numColors-1
tmp = Abs(red - OutputColors(k)\red) + Abs(green - OutputColors(k)\green) + Abs(blue - OutputColors(k)\blue)
If tmp < minval
minval = tmp
minindex = k
EndIf
Next
OutputColors(minindex)\count + 1
FrontColor(OutputColors(minindex)\red * 16, OutputColors(minindex)\green * 16, OutputColors(minindex)\blue * 16)
Plot(i, j)
Next
Next
StopDrawing()
ProcedureReturn outputimage
EndProcedure
;- example
inputimg = LoadImage(#PB_Any, "test.bmp")
outputimg = ReduceImageColors(inputimg, 16)
SaveImage(outputimg, "output16.bmp")
outputimg = ReduceImageColors(inputimg, 4)
SaveImage(outputimg, "output4.bmp")
MessageRequester("", "done")