Page 1 of 2

Anybody has worked with color quantization / posterizing before?

Posted: Mon Jul 15, 2024 7:41 pm
by SelfDevTv
Hi guys,

here is my problem:

Imagine a real life image with high resolution. In my game I will pixelate that image and then create pixels that the user can draw on (coloring pixels clone). The problem is the color palette. There are 1000s of colors in a single image. I need to decrease that to K colors.

In javascript i did that before with a library but I can't find any in love / lua.

So I tried myself for days now with the k-means algorithm, but it just doesn't work.

Now I want to ask, has anbody here worked with color quant before or do you know of any library that does that?
Important: I don't mean shaders. I need to apply the recoloring to the actual image data. I get this data already in this form:

Code: Select all

local function generatePixelsFromImage(imageData, pixelSize, totalColors)
    local pixels = {}
    local pixelSize = pixelSize or 10
    local totalColors = totalColors or 10

    local w = math.floor(imageData:getWidth() / pixelSize)
    local h = math.floor(imageData:getHeight() / pixelSize)

    for y = 0, h - 1 do
        for x = 0, w - 1 do
            local r, g, b = imageData:getPixel(x * pixelSize, y * pixelSize)
            table.insert(pixels, pixel(x, y, color(r, g, b)))
        end
    end

    return pixels
end

Re: Anybody has worked with color quantization / posterizing before?

Posted: Tue Jul 16, 2024 2:51 pm
by dusoft
Isn't it easier to use specialized software for that *before* putting it into your game? E.g. imagemagick or similar CLI tools.

https://www.imagemagick.org/Usage/quantize/#remap

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 8:24 am
by SelfDevTv
dusoft wrote: Tue Jul 16, 2024 2:51 pm Isn't it easier to use specialized software for that *before* putting it into your game? E.g. imagemagick or similar CLI tools.

https://www.imagemagick.org/Usage/quantize/#remap
I would say yes, but my game works in a way that it fetches a random image from an api, and then applies the pixelation + color quant to it, so thats not an option i think. I created a nodejs server, because in javascript there is a package that does that for me. That works, but i kinda wanted it to work in my game to not need another api request.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 10:41 am
by BrotSagtMist
I think you are looking for

Code: Select all

ImageData=love.image.newImageData("bla.png")
function pixelFunction(x, y, r, g, b, a)
    return (math.ceil(r*3)/3), (math.ceil(g*3)/3), (math.ceil(b*3)/3), a
end
ImageData:mapPixel( pixelFunction, x, y, width, height )
Image=love.graphics.newImage(ImageData)
function love.draw()
 love.graphics.draw(Image)
end

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 10:53 am
by pgimeno
BrotSagtMist wrote: Wed Jul 17, 2024 10:41 am I think you are looking for

Code: Select all

ImageData=love.image.newImageData("bla.png")
function pixelFunction(x, y, r, g, b, a)
    return (math.ceil(r*3)/3), (math.ceil(g*3)/3), (math.ceil(b*3)/3), a
end
ImageData:mapPixel( pixelFunction, x, y, width, height )
Image=love.graphics.newImage(ImageData)
function love.draw()
 love.graphics.draw(Image)
end
That's more like posterization, not quantization. Also, the * and / are reversed.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 11:09 am
by BrotSagtMist
The title says posterizing.
Also no, this is how its meant to be, i guess, no clue if that does proper posterizing. I only meant to hint at the mapPixel function.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 12:57 pm
by pgimeno
BrotSagtMist wrote: Wed Jul 17, 2024 11:09 am The title says posterizing.
Also no, this is how its meant to be, i guess, no clue if that does proper posterizing. I only meant to hint at the mapPixel function.
It's a good idea to test your examples before posting them. Here's a test of your quantization method for values 0 to 255:

Code: Select all

for r = 0, 255 do
  local quant = math.ceil(r*3)/3
  if quant ~= r then
    print("Quantization may be working")
    return
  end
end
print("Quantization is not working, all values are equal to their quantized version.")
It outputs "Quantization is not working, all values are equal to their quantized version." (tested, but I didn't expect otherwise, because multiplying an integer by 3 will return an integer, therefore math.ceil() will not alter it and the result is the same as r*3/3 which is like doing nothing).

It's also a good idea to read the text of the question and not just the title. The OP says "There are 1000s of colors in a single image. I need to decrease that to K colors."

If you want to hint at a function, you can use the [wiki]...[/wiki] markup: ImageData:mapPixel; you don't need to post bogus examples which will do nothing but confuse the person asking.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 2:40 pm
by BrotSagtMist
Maybe read that again man.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 4:13 pm
by pgimeno
BrotSagtMist wrote: Wed Jul 17, 2024 2:40 pm Maybe read that again man.
What, the OP text? It says "K colors", not "K equispaced levels per colour component", which is what your method would do if it worked. Maybe it's you who needs to read it again? How would you restrict an image to have, say, 23 colours? Applying a version of your method that works, you could get 23 levels per component, giving 23^3 = 12167 colours, but not 23. The OP also mentions the k-means algorithm, which aims to get the best colour palette with K entries for a given image; simple equispacing wouldn't work well.

Re: Anybody has worked with color quantization / posterizing before?

Posted: Wed Jul 17, 2024 5:56 pm
by BrotSagtMist
Dude, OP asked for posterizing and i gave an example that replicates gimps posterizing tool (minus being a shade off because math.ceil is unfit for this but whatevs).
Maybe you should actually run the code and compare it with an actual graphics tool before throwing a tantrum next time?
apendix: math.floor(r*k+.5)/k will replicate the exact gimp function, while k being off by 1 tho.