[?] Re-Mapping an image

BlitzMax Forums/BlitzMax Programming/[?] Re-Mapping an image

EOF(Posted 2005) [#1]
Do you have a quick way to re-map the colors in an image to a preset pallete?

Lets suppose I have loaded a typical 16 million color image and I want to change it's colors to a 4 color pallete of say:

0 - $000000 ' black
1 - $ffffff ' white
2 - $cc1211 ' red
3 - $32ef30 ' green

What routine/function would you use?
I have a modified GreyScale converter (Birdies) which is along the lines of what I'm trying to do:
Function ConvertToGreyScale(i:TPixmap)
  For Local y=0 Until i.height
    For x=0 Until i.width
      Local col = ReadPixel( i, x, y )
      Local a = ( col & $ff000000)
      Local r = ( col & $ff0000 ) Shr 16
      Local g = ( col & $ff00 ) Shr 8
      Local b = ( col & $ff )
      Local cc= (r+g+b)/3
      col = a | (cc Shl 16) | (cc Shl 8) | cc
      WritePixel i, x, y, col
    Next
  Next
EndFunction
The bit I'm stuck on is comparing the source pixel color with the available palette colors and choosing the nearest match.


Bertrand(Posted 2005) [#2]
Well, i put already an example in the Wiki, http://www.blitzwiki.org/index.php/ReadPixel

You can also try my GFX module:
http://blempereur.einden.com/work/bmaxmod/ag.mod.rar
The user guide online:
http://blempereur.einden.com/work/bmaxmod/commands.html


EOF(Posted 2005) [#3]
Are you planning on adding a 'RemapPixmap' function?
That is, a function that will remap a pixmap to a fixed set of palette colors?

BTW: Nice set of image manipulation functions.

I'm still in a muddle. Should I compare each R,G,B component of the source pixel against the list colors in the palette or use the argb result?

I need to find the closest matching color:
argb=ReadPixel(mypixmap,x,y)
For pal=EachIn PaletteList
 If pal.rgb {{is a close match to}} argb
   WritePixel mypixmap,x,y,pal.rgb
 EndIf
Next



EOF(Posted 2005) [#4]
Got it working by using:

For pal=EachIn palettelist
 r=Abs(sourceRed-palRed)
 g=Abs(sourceGreen-palGreen)
 b=Abs(sourceBlue-palBlue)
 pal.index=(r+g+b)/3
Next

After that, I sort the palettelist then pick off the first entry which is the closest match.


Bertrand(Posted 2005) [#5]
If you finish any pixmap function, i can add it to my module, send me, you can write yourself the doc and explaination.
Coz i'm not sure that i understand what you are trying to do.


EOF(Posted 2005) [#6]
I have the re-mapping almost perfectly working now. It's just a matter of choosing an easy way to implement it into your image processing functions. The awkward part is how to pass the palette set.

This is what my function does:

Takes a loaded pixmap, re-maps the colours in the image to a preset range of colours from a palette.

Example:



As you can see, the remapping code needs more work. It fails to pick CYAN as a close match for the background.

Currently, I have the palette stored in a TYPE with r,g,b fields. Basically, the routine just needs to run through a list of colours and choose the closest match.


ImaginaryHuman(Posted 2005) [#7]
Maybe you would get a better color match using Hue Saturation and Value, rather than RGB?

Also, how about dithering? Floyd Steinberg? That girl on the right looks ill ;-)


FlameDuck(Posted 2005) [#8]
Also, how about dithering? Floyd Steinberg? That girl on the right looks ill ;-)
Or something from the C64 days. Not really surprising considering the chosen palette.


ImaginaryHuman(Posted 2005) [#9]
Even with a limited palette it would look a lot more like the original with dithering, but then you have to look into building histograms of color usage and selecting an optimum palette.


EOF(Posted 2005) [#10]
Or something from the C64 days. Not really surprising considering the chosen palette
Well spotted that man. I'm doing a Retro screensaver which loads up an image from a given folder then converts it to a retro-style C64 screenie.
So far it pretty much looks the business.

Maybe you would get a better color match using Hue Saturation and Value
I'm almost there with RGB but I'm sure there was a formula for matching 3 values to a list which contains sets of 3 values. Any ideas?

What I'm doing at the moment is:
argb=ReadPixel(i,x,y)
srcR = (argb & $ff0000) Shr 16
srcG = (argb & $ff00)  Shr 8
srcB = (argb & $ff)
For pal=EachIn palettelist
	r=Abs(srcR-pal.r)
	g=Abs(srcG-pal.g)
	b=Abs(srcB-pal.b)
	pal.index=(r+g+b)/3
Next
SortList palettelist ' lowest index value comes first
fp:palette=palette(palettelist.first())
argb = $ff000000 | fp.r Shl 16 | fp.g Shl 8 | fp.b
WritePixel i, x, y, argb


I don't think this is the best way though.

Example:
source pixel color:
-------------------------
006,254,254 ' cyan


palette choices:
-------------------------
092,250,253 ' cyan
158,251,171 ' light green
My routine seems to choose light green here.