Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image palette is ignored #10

Open
RubenLagrouw opened this issue Dec 14, 2018 · 5 comments
Open

Image palette is ignored #10

RubenLagrouw opened this issue Dec 14, 2018 · 5 comments
Labels

Comments

@RubenLagrouw
Copy link

RubenLagrouw commented Dec 14, 2018

All input images are interpreted as having a white-black-red palette. Unfortunately lots of software does not let you choose the palette order.

I worked around it like this, but it would be nicer to honor the palette instead. (Of course red should be yellow if you have the yellow version...)

img = Image.open("temp.png")
cR = [255, 0, 0]
cB = [0, 0, 0]
cW = [255, 255, 255]

palette_old = img.getpalette()

p_conv = {0: palette_old[0:3],
        1: palette_old[3:6],
        2: palette_old[6:9]}

# p_target = {0: cW,
#             1: cB,
#             2: cR}

new_pixdata = []
old_pixdata = img.getdata()
for pix in old_pixdata:
    if pix not in p_conv:
        print('Pixel out of range: {}'.format(pix))
        new_pixdata.append(0)
    elif p_conv[pix] == cW:
        new_pixdata.append(0)
    elif p_conv[pix] == cB:
        new_pixdata.append(1)
    elif p_conv[pix] == cR:
        new_pixdata.append(2)

img.putdata(new_pixdata)
img.putpalette(cW + cB + cR)  # Goal palette
@mattdesl
Copy link

mattdesl commented Dec 17, 2018

I just ran into this with my own B&W inkypHAT. Here's what I'm using to take an arbitrary image and convert it to black or white pixels based on a threshold.

def reindex_image (other):
  rgb_im = other.convert('RGB')
  img = Image.new("P", (inky_display.WIDTH, inky_display.HEIGHT))
  for x in range(inky_display.WIDTH):
    for y in range(inky_display.HEIGHT):
      (r, g, b) = rgb_im.getpixel((x, y))
      color = inky_display.WHITE if r > 127 else inky_display.BLACK
      img.putpixel((x, y), color)
  return img

# Read your indexed PNG image ...
img = Image.open("foo.png")

# Reindex into black and white colors
img = reindex_image(img)

# buffer & show
inky_dispay.set_image(img)
inky_display.show()

@Gadgetoid
Copy link
Member

We should probably whip up an example with this approach, or perhaps build it in. I'm conflicted!

I was deliberately trying to make Inky image-library-agnostic, but that does make it difficult to re-introduce features such as palette-order.

Right now converting the image with PIL before displaying it on Inky is the "right" approach, but I'm not convinced it's the best.

@RubenLagrouw
Copy link
Author

I cannot do the conversion with PIL because it cannot handle my input images. Since i'm using imagemagick for conversion anyway, i can just as well do everything there. Except palette order, unfortunately. My workaround works for me, i hope it is useful for someone else too 😁

@aghster
Copy link

aghster commented May 31, 2020

The old inky-phat library had a colswap parameter in set_image that could be used to swap colors (see here). Of course, this does not really help honor the palette, but would make it easier to manually reorder the colors. IMO, reintroducing the colswap functionality would not conflict with the aim to make inky image-library-agnostic.

@rferrese
Copy link

This caused me a bit of trouble since I was trying to load PNGs and didn't have a good way to change the palette ordering. I made a python script to convert a PNG to the correct Black/White/Red colors for the 3 color display. I figured I'd share to save anyone else the trouble:

from PIL import Image

source = "old.png"
destination = "new.png"

# Open source file
oldimage = Image.open(source)

# Create palette.  Must contain 768 integer values
palettedata = [
    255, 255, 255,
    0, 0, 0,
    255, 0, 0
    ]
palettedata += [0] * (768 - len(palettedata))

# Create palette image
palimage = Image.new('P', (1, 1))
palimage.putpalette(palettedata)

# Quantize (change to dither=1 if you want dithering)
newimage = oldimage.quantize(palette=palimage, dither=0) 

# Save
newimage.save(destination, "PNG")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants