Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
I want to achieve 2.10 posturize with color-erase blending mode effect in python
#1
Hello, I am attempting to make a script of mine more efficient. I am trying to replicate the output of using posterize with the color-erase blending option in python without leaning heavily on gimp. Below is showing how posterize can influence an image's appearance.  
[Image: bugging-Me.png]
As you can see, this is what it looks like when I take the original photo, remove the alpha channel, and posterize. Below is one of the more interesting outcomes for the color-erase blending option when applied with the posterize tool.
[Image: asdaaa.png]
The step, by step instructions to get this effect:
1. Open image
2. Remove alpha channel of image by right clicking in layer menu
3. Select posterize from the color dropdown menu in the main window
4. In the posterize menu, select the color-erase blending mode and put the slider anywhere between 3 and 254.
Here's how to programmatically achieve the effect with Python-fu for 2.10:
Code:
groupLayer = pdb.gimp_layer_group_new(image)
srcLayer =  pdb.gimp_layer_copy(image.layers[0], False)
eraseLayer = pdb.gimp_layer_copy(image.layers[0], False)

#Insert layer group with two layers inside
pdb.gimp_image_insert_layer(image,groupLayer, None, -1)
pdb.gimp_image_insert_layer(image, srcLayer, image.layers[0], -1)
pdb.gimp_image_insert_layer(image, eraseLayer, image.layers[0], -1)

#Posterize erase layer, then set paint mode to Color Erase
pdb.gimp_layer_set_mode(eraseLayer, 57)
pdb.gimp_drawable_posterize(eraseLayer, amount)

#transfer grouplayer alpha to new mask, then fill alpha with white
mask = pdb.gimp_layer_create_mask(groupLayer, 3)
pdb.gimp_layer_add_mask(groupLayer, mask)
pdb.gimp_drawable_edit_fill(mask, 2)

# Apply mask and merge group
pdb.gimp_image_merge_layer_group(image, image.layers[0])
pdb.gimp_layer_remove_mask(image.layers[0], 0)

I'm interested in anything from theorizing, to gimp source-code that can explain how I could replicate this effect. I am curious how it works. If you've made it this far, thank you for reading my post!
Reply
#2
The Color erase mode computes the most transparent pixel under which you can stack the erased color to rebuild the initial color. For instance, yif you Color-erase a purple pixel with red, you are left with a partially transparent blue, and if you put this pixel over the erase red, you get the purple back.

   

In your case the result of the posterization is used as a temporary/virtual color-erase layer. If you had an infinite level of posterization, the posterized image would be identical to the source image, and all pixels would be color-erased by a copy of themselves and would turn fully transparent. With normal posterization levels, you color-erase pixels with whatever color the posterization would color them into, which is fairly random because that depends on the rest f the image and the posterization levels.... The only not-too-random part of the result is that since the pixel is replaced by the closest color in the posterization set it will be likely quite transparent. But since you throw away the alpha channel all you see is the residual color, which v very transparent pixels is not that accurate so you have a bit of randomness here too, especially in 8bpc mode.

IMHO you would get very similar results, by 1) color-indexing the image, and 2) assigning random values in the color map.


Source of color-erase mode is here (starts at line 1180 in the current master version).
Reply
#3
(07-12-2023, 07:01 AM)Ofnuts Wrote: The Color erase mode computes the most transparent pixel under which you can stack the erased color to rebuild the initial color. For instance, yif you Color-erase a purple pixel with red, you are left with a partially transparent blue, and if you put this pixel over the erase red, you get the purple back.



In your case the result of the posterization is used as a temporary/virtual color-erase layer. If you had an infinite level of posterization, the posterized image would be identical to the source image, and all pixels would be color-erased by a copy of themselves and would turn fully transparent. With normal posterization levels, you color-erase pixels with whatever color the posterization would color them into, which is fairly random because that depends on the rest f the image and the posterization levels.... The only not-too-random part of the result is that since the pixel is replaced by the closest color in the posterization set it will be likely quite transparent. But since you throw away the alpha channel all you see is the residual color, which v very transparent pixels is not that accurate so you have a bit of randomness here too, especially in 8bpc mode.

IMHO you would get very similar results, by 1) color-indexing the image, and 2) assigning random values in the color map.

Source of color-erase mode is here (starts at line 1180 in the current master version).

First of all, thank you Ofnuts for your input. It's been a while since I attempted this project. I have nearly succeeded at my process of replicating the desired posterize + color-erase effect using python, numpy, and PIL. I am currently hung up on replicating the exact output of my gimp process.


I am only making a new post here because I am pretty stuck. Seems I may have missed some subtle nature of gimp that could be affecting gimp's output versus my limited understanding of the process.

I have theorized that it could be something to do any or none of these processes:
  • The blending of the images
  • the alpha calculation for the color-erase
  • A default palette or preset within gimp that produces the particular color combination.
There is a subtle difference between the outputs produced by gimp and my python program. I will give an example of this difference. My output appears to be producing more intense highlights and shadows. I heavily suspect this has to do with how I am calculating the alpha mask for blending the posterize layer with the original image.

Example:

Gimp posterize with 2 levels using color-erase blending option:
[Image: bug-scaled-posterized-2.png]

Python replication of gimp 2.10 posterize and color erase algorithm:
[Image: bug-posterized-scaled-python-2.png]
Original image:
[Image: bug-scaled.png]

If more information is necessary please let me know. I'm appreciative and open to any suggestions on how I can solve this issue.
Reply
#4
You are likely working directly on gamma-corrected values instead of "linear light". See my answers in this thread: https://www.gimp-forum.net/Thread-Layer-...cial-guide.

Not included in the referenced post but something equivalent exists for layer masks. The gamma-corrected grayscale value of a 50% opacity layer mask is #BC, and a black layer over white or a white layer over black with a mask with #BC will produce a the middle gray which is also #BC.

Some more info here:  https://en.wikipedia.org/wiki/SRGB#Transformation

The python functions that implement the sRGB transforms (and give identical result to Gimp as far as my tests go):

Code:
import math

# Linear is [0.0 .. 1.0]
# sRGB is [0 .. 255]

def srgbToLinear(v255):
   v=v255/255.
   return v/12.92 if v <= 0.04045 else math.pow((v+0.055)/1.055,2.4)

def linearToSrgb(linear):
   srgb=linear*12.92 if linear < 0.0031308 else 1.055*math.pow(linear,1/2.4)-0.055
   return 255*srgb

... but if you process whole images I hope you are using numpy or equivalent.
Reply
#5
So, I had a writeup on this in the works, and finished it, so you can check it here: https://www.gimp-forum.net/Thread-What-i...ions-wrong
Reply
#6
(07-16-2024, 09:38 PM)Ofnuts Wrote: So, I had a writeup on this in the works, and finished it, so you can check it here: https://www.gimp-forum.net/Thread-What-i...ions-wrong

You were right on the money here Ofnuts! That was the final piece I needed to finish replicating the color-erase posterize effect in python! Now I can finally move onto something else. I dedicate this next PNG to your supreme helpfulness:

[Image: image.png]
Reply


Forum Jump: