Use a list to updatePixels()

Hallo everyone,
I have a List of RGB values (technically all grey, in the form of (255, 255, 255), (204, 204, 204), (255, 255, 255) etc.) that I would like to display as an image. From my understanding, the updatePixels() command only lets you use the pixels previously loaded through loadPixels(), but not from an entirely different source (e.g. a list). Or alternatively, is there any way to accomplish this through simply using set()?
Thanks in advance!

1 Like

Can you post how that list is created?
A PImage is basically an int[] array, plus the fields width & height.

The code is quite bad, but I ended up with the list I wanted (I think). It’s from five different versions of the same image, five different thresholds, giving me five lists of 0s and 1s. I manually added up the values and assigned them the grey values I wanted – that’s where I’m stuck.
Basically this times five:

global img
    background(0);
    image(img,0,0)
    t = 0.75
    filter(THRESHOLD, t)
    loadPixels()
    liste4 = (pixels)
    
liste75 = []
    for x in liste4:
        if x == -16777216:
            liste75.append(0)
        if x == -1:
            liste75.append(1)

Plus then adding the values of each list, giving me 0-5 and assigning e.g. 0 = (0,0,0) and 1 = (51,51,51) etc.

1 Like

Let’s see if I get it:

  • You’ve got a palette of 6 grays.
  • You’re attempting to convert the current canvas pixels[]'s colors in 1 of those 6 grays into a separate list.
  • But then you need to turn that grey list back to a PImage, so it is displayable too.

Am I guessing right?

Pretty much that! The list with those 6 greys I do have already, turning the list back into a displayable image is where I have been stuck.
Everything that has to do with the “Pixels” command seems to be limited to load and update, I just don’t know where I can feed this list back into the equation.
And thank you for taking your time!

Im not good with python, but in Java you can just use :

loadPixels();
   for (int i = 0; i < pixels.length; i++) {
      pixels[i] = liste[i];
   }
updatePixels();

Now you‘ll have to translate this to pyton… which i‘m not good at, as i said…

Note, this only works if both have the same length.

Thank you! I’m quite new to all of this, so let me see how this goes, I’ll report back if it worked!

Edit:

img.loadPixels()
    for i in range(len(img.pixels)): 
        pixels[i] = list(RGBList)
    img.updatePixels()

That should be the equivalent? It says “an integer is required” in place of the " = list() ". I feel like I’m missing something quite obvious?

I‘m not too good with Python, but i googled the list() function and it seems to only return a list. That’s not what you need, you need an individual Int.

Apparently in Python you can also just use [i] to get the Element at that index. So use RGBList[i] instead of list(RGBList)

Also, you have to use img.pixels[i].

Something like this?

img = createImage(50, 50, RGB)

RGBList = [
  (51, 51, 51),
  (51, 51, 51),
  ...
]

for i in range(len(img.pixels)): 
    rgb = RGBList[i]
    img.pixels[i] = color(rgb[0], rgb[1], rgb[2])

image(img, 0, 0)
  • filter() already got the GRAY type: Py.Processing.org/reference/filter.html
  • It converts all colors to 1 of the 256 grey tones.
  • You state you require 6 shades instead.
  • So we just need to use POSTERIZE after GRAY in order to get the desired effect:
"""
 Gray Posterized PImage (v1.0.1)
 GoToLoop (2019-Dec-09)
 https://Discourse.Processing.org/t/use-a-list-to-updatepixels/16268/10
"""

def hex6Digits(v): return str(hex(v, 6))
def mapToHex(container): return tuple(map(hex6Digits, container))

FILENAME = (
    'https://' 'Upload.Wikimedia.org' '/wikipedia/commons/thumb/2/2e/'
    'Processing_3_logo.png/' '240px-Processing_3_logo.png')

IMGS, NUM_GREYS, COLOR_OCTET, BG = 3, 6, 0xff, 0300
GREY_INTERVAL = COLOR_OCTET / (NUM_GREYS - 1)

GREYS_RANGE = tuple(range(0, COLOR_OCTET + 1, GREY_INTERVAL))
GREYS = tuple(color(grey) for grey in GREYS_RANGE)

print FILENAME
print GREYS_RANGE, len(GREYS_RANGE)
print mapToHex(GREYS), len(GREYS)

def settings():
    global original, greyed, posterized

    original = loadImage(FILENAME)
    greyed, posterized = original.get(), original.get()

    size(IMGS * original.width, original.height)
    noLoop()


def draw():
    background(BG)
    set(0, 0, original)

    transferPixels(original, greyed)
    greyed.filter(GRAY)
    set(width / IMGS, 0, greyed)

    transferPixels(greyed, posterized)
    posterized.filter(POSTERIZE, NUM_GREYS)
    set(2 * width / IMGS, 0, posterized)

    posterized.loadPixels()
    unique_colors = set(mapToHex(posterized.pixels))
    print unique_colors, len(unique_colors)


def transferPixels(src, dst):
    src.loadPixels()
    arrayCopy(src.pixels, dst.pixels)
    dst.updatePixels()
3 Likes

Oh wow, that’s crazy! That is definitely beyond my level, but a great resource to learn how it works, thank you!
Maybe I can re-write what I had along your solution, at the moment I’m doing this mainly to understand the basics.

The reason I made it complicated in the first place (with the five lists from from the five images) was because I tried to “replicate” the steps used, when they sent Images through wire for the first time, almost a hundred years ago, with this system: https://petapixel.com/assets/uploads/2013/07/pIqE68N.jpg
To keep it short, there the image is split into five different exposures, etched on copperplates, which are then simultaneously read and translated onto a perforated tape, containing the values 0-5, telegraphed and on the other side of the Atlantic then translated back into an image.

Again, thanks a lot for your help!

2 Likes