Author Topic: [BMAX + MaxGUI] Filter photos.  (Read 8105 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
[BMAX + MaxGUI] Filter photos.
« on: February 24, 2008 »


I've had some algorithems I've wanted to use at a pixel level. I plan to try some things like blurring and inverting and some more advanced "filters". My question is how do I edit Timages? Should I be using Timages even when pixmaps are available? Also, I wish the preserve the alpha channel of pixels found in .png images. I look forwared to making my own filter effects for photographs.

Thanks for any help you guys have.
Challenge Trophies Won:

Offline a

  • ZX 81
  • *
  • Posts: 21
  • Karma: 0
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #1 on: February 25, 2008 »
AFAIK, images are better for drawing and stuff like you would do in a game and pixmaps are better for editing, but MUCH slower in drawing. also, pixmaps can be converted to other stuff(textures, images) or colordepth/size can be changed easily. but when you want to do effects and not draw much stuff like in a game but just some images i guess pixmaps would be the better solution. but remember the conversion from pixmaps to images takes much time, too.

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #2 on: February 25, 2008 »
You cannot edit TImages directly, you will have to use pixmaps. But you can easily convert a pixmap to an image.

Code: [Select]
pMap:TPixmap = createpixmap(256,256)
img:TImage = loadimage(pMap)

You can directly edit pixmaps either by using write/readpixels commands, or getting the pointer to the pixmap and access the rgba values directly. You can convert an image to a pixmap by using the LockImage() command.

Here is an example of an invert filter function.

Code: [Select]
Graphics 1024,768

Local sourceImg:TImage = LoadImage("testimage.png",0)
Local destImg:TImage = invertFilter(sourceImg)

Cls

DrawImage(sourceImg,0,0)
DrawImage(destImg,256,0)

Flip
WaitKey()
End

Function invertFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap,0,0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int
Local r:Int,g:Int,b:Int
Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h-1
tmpPixmapPtr[x*4+y*4*w] = 255-sourcePixmapPtr[x*4+y*4*w] 'red
tmpPixmapPtr[x*4+y*4*w+1] = 255-sourcePixmapPtr[x*4+y*4*w+1] 'green
tmpPixmapPtr[x*4+y*4*w+2] = 255-sourcePixmapPtr[x*4+y*4*w+2] 'blue
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function
« Last Edit: February 25, 2008 by zawran »

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #3 on: February 26, 2008 »
Thanks, I was hoping you would answer. I know you are making a similar tool.

Would you have a minute to explain how the pointers you've used work?

Some fruits of my labors so far. I'm REALLY having fun with these.


« Last Edit: February 26, 2008 by Pixel_Outlaw »
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #4 on: February 26, 2008 »
The pixmap pointer is a variable that points directly to the pixel data within the pixmap. The pixels in the pixmap is put together of four values. Red, Green, Blue and Alpha. These values are represented with bytes, so the 4 bytes makes up an Int, which is the value size you would use when using the writepixel function. When dealing with the pixel data directly, we save some processing time, but we will have to do our own bound checking. The read/writepixel functions are slower because they do a lot of checking to make sure that nothing goes wrong.

Lets say that you are using a 256x256 pixels bitmap. And lets say that you have loaded this image into bmax as a pixmap. Then using the function called PixmapPixelPtr() we can get a pointer to the pixel data within that pixmap. This function returns a byte pointer to the location within the pixmap that you specify. Usually with full image manipulation you would choose 0,0 as the starting value to point to. Since its a byte pointer, it will point to each byte, and since we know that each pixel is made up of 4 bytes, we need to increase the pointer by 4 to reach the next pixel. This is why you see all those *4 in the code.

I am not sure if this is info enough, but do ask away, and I will try and answer as best as I can.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #5 on: February 26, 2008 »
Ahhhh the * 4 bits were throwing me off. I do understand now thanks.

Working on a 4x4 matrix dithering algorithem. My head hurts.
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #6 on: February 27, 2008 »
Here is an example of the filters I have done so far:



The flip filter can do vertical, horizontal and both. The mask filter can filter red,green,blue and any combination of those. The contrast filter also does brightness. At the moment I am working on a matrix filter function which should enable me to do boxblur, motionblur, edge detection, sharpen and emboss. There are lots of other filters to do, but not that much easy to understand documentation on how to make them.

I just completed a matrix filter and did a bunch of test to see what filter effects could be done with it and here is the result so far:



To avoid going beyond the limit of the pixmaps the filter wraps around the edges, which sometimes results in odd looking pixels on the edge. Alternative is to detect when its outside the pixmap and set the result as zero, but I am not sure that would produce much better looking images.
« Last Edit: February 27, 2008 by zawran »

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #7 on: February 27, 2008 »
Wow, all impressive stuff. One thing that really caught my eye is the grass in the 'sharpen regular'

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #8 on: February 28, 2008 »
I'm really having trouble with a dither filter. I have made an 4x4 set of gradient brushes with 17 sub images. I think you could take your block effect then convert that to grayscale then choose the correct 4x4 subimage and draw the brush on to the output image.

I'm making this program and I'm sort of in a bind. Would you mind taking a stab at the dithering using my dither brush pattern? I'll give you credit of course!


Here you have 17 4x4 patterns ranging from black to pure white. I like the idea of different dithering patterns so I wanted to be able to load a brush pattern rather than to the matrix trickery.

Here is the 17 image dither pattern


Here is my source I have some color reduction filters and other fun things.

Code: [Select]
Strict
Graphics 1024, 768
' the dither brush image is 17 4x4 images used for dithering ranging from full black to pure white
' to dither you must average 4x4 areas of the image then write the proper dither brush pattern to the new image
' dither brush goes from black 0 to full white 16
Local dither:TImage = LoadAnimImage("dither_brush1.png", 4, 4, 0, 17)
' supply an image named testimage.png
Local sourceImg:TImage = LoadImage("car.png")
Local destImg:TImage = drugFilter(sourceImg)
Local destImg2:TImage = gradientFilter(sourceImg, 64, 0, 64, 255, 200, 0)
Local destImg3:TImage = spatterFilter(sourceImg)
Local destImg4:TImage = colormidtoneFilter(sourceImg, 5)
Local destImg5:TImage = RGBFilter(sourceImg)
Cls

DrawImage(sourceImg,0,0)
DrawImage(destImg,256,0)
DrawImage(destImg2, 512, 0) 
DrawImage(destImg3, 256, 380)
DrawImage(destimg4, 512, 380)
DrawImage(destimg5, 0, 380)
Flip
WaitKey()
End

Function round:Float(n:Float)
Local r:Float = n Mod 1
If r >=.5
Return Ceil(n)
Else
Return Floor(n)
EndIf
End Function

Function invertFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
tmpPixmapPtr[x * 4 + y * 4 * w] = 255 - red 'red
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = 255 - green 'green
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = 255 - blue 'blue
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function grayscaleFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue = sourcePixmapPtr[x * 4 + y * 4 * w + 2]

Local gray = Float(red + blue + green) / 3.0
tmpPixmapPtr[x * 4 + y * 4 * w] = gray 'red
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = gray 'green
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = gray    'blue
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function midtoneFilter:TImage(source:TImage, midtones:Float = 6)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w - 1
For y = 0 To h - 1
Local red:Float = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
Local total:Float = red + green + blue
Local color:Float = Null

Local midtone_percent:Float = round(total / 765 * midtones)

color = 255 / midtones * midtone_percent
tmpPixmapPtr[x * 4 + y * 4 * w] = color
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = color
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = color
tmpPixmapPtr[x * 4 + y * 4 * w + 3] = sourcePixmapPtr[x * 4 + y * 4 * w + 3]
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function colormidtoneFilter:TImage(source:TImage, midtones:Float = 6)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w - 1
For y = 0 To h - 1
Local red:Float = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
Local red_midtone_percent:Float = round(red / 255 * midtones)
Local red_color = 255 / midtones * red_midtone_percent
Local green_midtone_percent:Float = round(green / 255 * midtones)
Local green_color = 255 / midtones * green_midtone_percent
Local blue_midtone_percent:Float = round(blue / 255 * midtones)
Local blue_color = 255 / midtones * blue_midtone_percent
tmpPixmapPtr[x * 4 + y * 4 * w] = red_color
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = green_color
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = blue_color
tmpPixmapPtr[x * 4 + y * 4 * w + 3] = sourcePixmapPtr[x * 4 + y * 4 * w + 3]
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function
 
Function drugFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red:Float = Sin(Float(sourcePixmapPtr[x * 4 + y * 4 * w] ) / 255 * 360) * 255
Local green:Float = Sin(Float(sourcePixmapPtr[x * 4 + y * 4 * w + 1] ) / 255 * 360) * 255
Local blue:Float = Sin(Float(sourcePixmapPtr[x * 4 + y * 4 * w + 2] ) / 255 * 360) * 255

tmpPixmapPtr[x * 4 + y * 4 * w] = red 'red
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = green 'green
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = blue    'blue
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function gradientFilter:TImage(source:TImage, r1:Float, g1:Float, b1:Float, r2:Float, g2:Float, b2:Float)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red:Float = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
Local percent:Float = (red + green + blue) / 765
tmpPixmapPtr[x * 4 + y * 4 * w] = r1 + (r2 - r1) * percent
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = g1 + (g2 - g1) * percent
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = b1 + (b2 - b1) * percent
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function spatterFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red:Float = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
Local percent:Float = Float(Rand(0, 255)) / 255
tmpPixmapPtr[x * 4 + y * 4 * w] = red * percent
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = green * percent
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = blue * percent
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

Function RGBFilter:TImage(source:TImage)
Local sourcePixmap:TPixmap = LockImage(source)
Local sourcePixmapPtr:Byte Ptr = PixmapPixelPtr(sourcePixmap, 0, 0)
Local tmpPixmap:TPixmap = CopyPixmap(sourcePixmap)
Local tmpPixmapPtr:Byte Ptr = PixmapPixelPtr(tmpPixmap,0,0)
Local x:Int,y:Int

Local w:Int = tmpPixmap.width
Local h:Int = tmpPixmap.height

For x = 0 To w-1
For y = 0 To h - 1
Local red:Float = sourcePixmapPtr[x * 4 + y * 4 * w]
Local green:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 1]
Local blue:Float = sourcePixmapPtr[x * 4 + y * 4 * w + 2]
Local saturation:Float = (red + green + blue) / 765
If red = 255 And green = 255 And blue = 255
red = 255
blue = 255
green = 255
End If

If red >= (green + blue) / 2
red = 255
green = 0
blue = 0
End If

If green >= (red + blue) / 2
red = 0
green = 255
blue = 0
End If

If blue >= (red + green) / 2
red = 0
green = 0
blue = 255
End If
tmpPixmapPtr[x * 4 + y * 4 * w] = red * saturation
tmpPixmapPtr[x * 4 + y * 4 * w + 1] = green * saturation
tmpPixmapPtr[x * 4 + y * 4 * w + 2] = blue * saturation
tmpPixmapPtr[x*4+y*4*w+3] = sourcePixmapPtr[x*4+y*4*w+3] 'alpha
Next
Next
Local tmpImage:TImage = LoadImage(tmpPixmap)
Return tmpImage
End Function

My filters:


Normal,Grayscale Midtones (5), Grayscale
Color midtones ( 2 ),Color Invert, Color Midtones(9)



Normal, Sin(component/255*360)*255,Map to color gradient (purple to orange here)
R or G or B +Values,Random black Spatter, Color Midtones(9)
« Last Edit: February 28, 2008 by Pixel_Outlaw »
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #9 on: February 28, 2008 »
It looks like you are going strong with making filter functions :)   I haven't looked at dither filters yet. I was thinking about trying for a floyd-steinberg function. I will have to read up on it first though as I have no idea how its done.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #10 on: February 28, 2008 »
It looks like you are going strong with making filter functions :)   I haven't looked at dither filters yet. I was thinking about trying for a floyd-steinberg function. I will have to read up on it first though as I have no idea how its done.

Thanks a lot. Really most of the time I just need a small "push" or to be shown how something is done then I can sort of blossom out.

Personally I like Bayer dithering because it has nice cross hatching style strokes.
http://en.wikipedia.org/wiki/Dither
« Last Edit: February 28, 2008 by Pixel_Outlaw »
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #11 on: March 03, 2008 »
I got it working after about 4 hours of tinkering.

I have two examples one done with bayer style and another done in the first dither brush pattern.

The trees take between 30 and 40 milliseconds to process. :whisper:
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #12 on: March 03, 2008 »
looking at some of your images game me an idea Zawran. While I was impressed with the image sharpening it still has that aliasing effect on edges so I've tried taking one of your edge filter images to make an alpha map and use that to blend the original and the sharpened image together.
It could probably be done much better than this but it kind of gives the idea.


Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #13 on: March 03, 2008 »
@Stonemonkey, it looks interesting, I will take a stab at it when I get time. Tonight I did 2 dithering filters. An average/threshold and an ordered.



I was going to do a floyd-steinberg or Stucki because they look great, but I still haven't managed to make any working code.

@Pixel_outlaw, your dither images looks great, so I can see that you managed just fine. Isn't it great to get something working? Its what keeps me coding most of the time, the challenge of making things work.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #14 on: March 11, 2008 »
I've wanted to make some filters that make photo's look human drawn. Things like sketch and crosshatching ect.

Oh and here is a photo of some guy in sepia tone.
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #15 on: March 11, 2008 »
Great to see that you still soldier on with this. I was going to post something this past weekend, but just didn't find time to do any coding. Luckly I am getting some vacation time soon (the entire next week), so with less work I will have more time to do some coding.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [BMAX + MaxGUI] Filter photos.
« Reply #16 on: March 11, 2008 »
Yes I'm very happy with this little project since it is math and somewhat art. It would be hard to emulate a human artist but at some level it should be able to be done. Photoshop has some filters but the results are shoddy. I would like some pencil and paper looking filters too.

My current question is how to force an image to a lower number color palette.

This is a quick algorithem that I have yet to impliment.

1 Set up two lists one to hold temporary data and one to hold output data.
2 Store every color in the initial image into a color object and save to the output data list.
3 If there are an odd number of colors discard the least important color.
4 For each color object find the closest match, remove both colors average them then save them to the temporary list.
5 The output list should now be set to equal the value of the temporary list and the temporary list should be cleared.

Repeat steps 4-5 as desired the total number of colors will be halved every time.

6 For each pixel in the initial image find the closest match in the output list and set that value.

I'm not quite how to find the closest color though. There is a possibility that two palette colors are equidistant from the color to be replaced.

To remidy this I planned to use a second comparison. First the colors should be compared by HSV then by RGB if they are equidistant from the color to be replaced. I hope this is right. I'm just jotting down theroy untill I can work on it.


« Last Edit: March 11, 2008 by Pixel_Outlaw »
Challenge Trophies Won: