Converting to index color gives incorrect results

Hi, I love the program but I’ve got a problem with the 1.2.9 I currently have. When I bring in art from another program, make a palette from the art, and then downsample to index color the colors chosen aren’t always the correct ones even if they exist in the palette. I think this can be reproduced easily.

-Make a new document (rgb).
-Put two colors down but make them only one or two integers apart in one channel.
-Make palette from image (should end up having only have three entries with the background color).
-Convert to Index color.

At this point Aseprite will just make both strokes the same color of one of the palette colors even though the palette contains both colors.

This is kind of a big problem because I have a habit of making images in other programs sometimes and am losing info when I try to bring them over. I’d appreciate any help or advice about a different process or setting I could use.

2 Likes

Well if anyone reads this could you take a sec to check if you can even re-create this behavior? I’d really like to know if it’s the program or if I’ve just been slipped the crazy pills.

Yup. If I draw two lines where one is #527b2e (82,107,46) while the other one is #526a2f (82, 106, 47), then make sure both are in the palette and switch to indexed mode they both become #526b2e.

I have no idea why this is the case. All I can think of is that either it’s a bug, or it’s working as intended and the indexed limitation causing this (or warranting this behavior) exists within the file types somehow.

I’ve to check some issues converting RGB -> Indexed (even more, replacing the whole algorithm to generate palettes from RGB images). So it’s something with high priority.

I’ve found the previous issue reporting this:

Thanks for posting here.

Can I make a suggestion, if there’s going to be a different system can there be an option for an exact mode? By that I mean the function would just be two loops where for each pixel of the document, it checks every pixel of the palette, and if an exact match is found then it’s accepted and if it isn’t then instead of choosing the next best color it actually stops the process and alerts the user?

Those of us who get really anal about colors would appreciate it.

1 Like

So it’s been about a year since I posted this, although it’s been 2 and a half years since someone made this other thread…

I tried the latest patches and I’m glad to see all the other bug fixes and features but I’m still getting the issue here. Is this something that is on the radar at all or should I stop worrying about it?

I feel the need to ask because I still find myself having to double-check doodles that I might start in Photoshop or something when I want to turn them into something more orderly in Aseprite.

1 Like

I agree this is important step when creating sprites, it makes them unusable, this even shouldnt be in aseprite cause results are very random when converting from non indexed pngs, there should be some way to at least feed it some palette, JASC animation shop has this, and works better to convert 24 bit pngs to indexed.There is also program called PALAPPLY that can do this .Maybe it could be merged into aseprite ? Please fix this !

We have a patch ready to be released, but it needs some testing, we’ll try to include it in a beta version in the Steam branch. Today I would like to release a new version without big changes, and then other beta with those extra changes (this bug fix included).

is this bug fixed yet?
i seem to continue having that issue.
i’m currently on version v1.2.25

i’m still having this issue, with <256 colors , even when I create new palette from the sprite project i’m working on, when I convert it to index, several colors change (with no option to remap). is this something to do with opacities?

Hi @ash3s,

If possible, please post a screen capture and say whether you’re using Octree or Table RGB 5 bits to convert.

For some posters on this thread, the issue is complicated by the fact that images created in Photoshop may have a different color profile than standard RGB. Go to Sprite > Properties to check. If the profile does not say sRGB, test if Converting to SRGB before creating a palette makes a difference.

If you want to try a script that creates a palette, see if this gives you different results:

-- Change these settings to preference.
local removeAlpha = false
local prependMask = true
local clampTo256 = true

local activeSprite = app.activeSprite
if not activeSprite then return end

-- Optional. Remove double hyphen to re-enable.
-- activeSprite:convertColorSpace(ColorSpace { sRGB = true })

local activeSpec = activeSprite.spec
if activeSpec.colorMode ~= ColorMode.RGB then
    return
end

local alphaMask = 0x0
if removeAlpha then
    alphaMask = 0xff000000
end

local dictionary = {}
local idx = 1

for _, activeFrame in ipairs(activeSprite.frames) do
    local flatImage = Image(activeSpec)
    flatImage:drawSprite(
        activeSprite,
        activeFrame,
        Point(0, 0))
    local itr = flatImage:pixels()

    for elm in itr do
        local hex = elm()
        if ((hex >> 0x18) & 0xff) > 0 then
            hex = alphaMask | hex
            if not dictionary[hex] then
                dictionary[hex] = idx
                idx = idx + 1
            end
        end
    end
end

local hexes = {}
for k, v in pairs(dictionary) do
    hexes[v] = k
end

if prependMask then
    local maskIdx = dictionary[0x0]
    if maskIdx then
        if maskIdx > 1 then
            table.remove(hexes, maskIdx)
            table.insert(hexes, 1, 0x0)
        end
    else
        table.insert(hexes, 1, 0x0)
    end
end

local hexesLen = #hexes
if hexesLen > 0 then
    local palLen = hexesLen
    if clampTo256 then
        palLen = math.min(256, hexesLen)
    end
    local palette = Palette(palLen)
    for i = 1, palLen, 1 do
        local hex = hexes[i]
        local aseColor = Color(
                      hex & 0xff,
            (hex >> 0x08) & 0xff,
            (hex >> 0x10) & 0xff,
            (hex >> 0x18) & 0xff)
        palette:setColor(i - 1, aseColor)
    end
    activeSprite:setPalette(palette)
end

app.refresh()

I don’t recommend using this script with a sprite that could generate a large palette (i.e., greater than 256). It could be slow and lock up Aseprite until it’s finished. It is not designed to work with any color mode other than RGB.

See also: Octree Color Indexed Conversion Testing ,
New Script for perfect palette generation from RGB sprite .

Cheers,
Jeremy

indexed:

rgb:

Hi thanks for the reply.

This is from a .gif animation with a 256 color table that I exported from PShop. When I open it in aseprite it looks fine. If I convert it to indexed, the colors slightly shift. This was using the default RGB conversion, not Octree.This is a single layer gif so no opacities or layer modes are being used.

I just upgraded to the beta, and tried the same file conversion and everything looks good!-- I dont see any differences, I think Octree has resolved this issue for me.

1 Like

I do not like necro-bumping an old thread, but I believe mentioning this also has a place in this thread because this is very similar. Although conversion of an RGB color image to indexed seems to have been improved via Octree as depicted above, this still produces inaccurate results as of v1.3-rc2 particularly if you instead use a different palette than the colors of an image. No improvement with Table RGB 5 bits + Alpha 3 bits.

Neither can produce visually accurate results when converting an RGB color sprite to a different palette which often requires manual recoloring. A palette with a difference in hue, saturation, lightness than the source image can make it lighter/darker than it should be or ruin conversion and make the image unusable. Unfortunately as well, I found that conversion from a RGB color sprite to indexed with a limited grayscale palette results in an image darker than it otherwise should be including if the colors and the available grey colors have closely matching luminosity. If an image is converted to grayscale, it can still pick the wrong colors.

I used the eyedropper tool with best fit index on a sprite I made which is equivalent to converting an RGB color sprite to indexed with a palette. The sprite is made of 7 colors. The palette used is a generated gradient of 64 grayscale values between black and white. In the center is the sprite with best fitting values when using that grayscale palette according to the human eye. Depicted with red text is the sprites with the wrong colors. Converting an image to indexed should match pixels of an image to their closest perceptually equivalent color in a palette to match more closely to the manually recolored sprite, but that ideal behavior is not quite here yet.

1 Like