02-13-2025, 02:42 PM
There is no pdb call for Exposure setting.
How do I do the equivalent?
Thank you in advance
How do I do the equivalent?
Thank you in advance
Exposure for Plug-in
|
02-13-2025, 02:42 PM
There is no pdb call for Exposure setting.
How do I do the equivalent? Thank you in advance
02-13-2025, 09:29 PM
I even went as far as trying to read code gegl/exposure.c
and can't get it to produce the same here's my python call def simulate_gimp_exposure(img, drawable, black_level=0.002, exposure=1.696): pdb.gimp_image_undo_group_start(img) # Get the current layer layer = drawable # Get the pixel data width, height = layer.width, layer.height srcRgn = layer.get_pixel_rgn(0, 0, width, height, False, False) src_pixels = array("B", srcRgn[0:width, 0:height]) dstRgn = layer.get_pixel_rgn(0, 0, width, height, True, True) p_size = len(srcRgn[0,0]) dest_pixels = array("B", "\x00" * (width * height * p_size)) # white = math.pow(2.0, -exposure) # Equivalent to exp2f(-exposure) # diff = max(white - black_level, 0.000001) # gain = 1.0 / diff # Normalize brightness scaling # **Apply Exposure Negation** (Key part of GIMP logic) exposure_negated = -exposure # ✅ This is how GIMP negates exposure white = math.pow(2.0, exposure_negated) # ✅ Equivalent to exp2f(exposure_negated) # Ensure we don't divide by zero in the gain calculation diff = max(white - black_level, 0.000001) gain = 1.0 / diff # Normalize brightness scaling # Read pixel data as bytes #data = bytearray(srcRgn[0:width, 0:height]) # Convert to mutable array data = src_pixels # Determine number of channels (RGB = 3, RGBA = 4) bpp = len(data) // (width * height) p_size = bpp dest_pixels = array("B", "\x00" * (width * height * p_size)) # Convert to float, apply black level & exposure, and store back exposure_factor = 2**exposure for i in range(0, len(data), bpp): r, g, b = [float(data[i + j])/255.0 for j in range(3)] a = data[i+3] # **Apply GIMP Exposure Math** r = (r - black_level) * gain g = (g - black_level) * gain b = (b - black_level) * gain # Clip values to (0,1) range r, g, b = [min(max(x, 0.0), 1.0) for x in (r, g, b)] # Convert back to 8-bit (0-255) r, g, b = [int(x * 255) for x in (r, g, b)] dest_pixels[i] = r dest_pixels[i+1] = g dest_pixels[i+2] = b dest_pixels[i+3] = a # Copy the whole array back to the pixel region: # Apply modified data back to the image #pixel_rgn[0:width, 0:height] = bytes(data) #pixel_rgn.set_pixels(0, 0, width, height, bytes(data)) dstRgn[0:width, 0:height] = dest_pixels.tostring() #pixel_rgn[0:width, 0:height] = dest_pixels.tostring() layer.flush() layer.merge_shadow(True) layer.update(0, 0, width, height) # Mark the region as modified pdb.gimp_image_undo_group_end(img) pdb.gimp_displays_flush()
02-13-2025, 09:37 PM
(02-13-2025, 02:42 PM)trandoductin Wrote: There is no pdb call for Exposure setting. It's a GEGL filter. Somewhat easy in GIMP3. In Gimp2, as far as I cant tell the steps are photographic exposure values (aka EV), and one EV is twice as more light. So you convert the value to linear, and multiply by 2^exposure_correction. Of course you don't do this on a pixel basis (unless you have numpy) but you can compute several values for Curves and then apply Curves. I didn't try but you can tell Gimp 2.10 that your plugin understands linear mode (pdb.gimp_plugin_enable_precision()) and this may avoids having to do sRGB<->Linear conversions.Otherwise you can help yourself to my Python code.
02-14-2025, 12:17 AM
(This post was last modified: 02-14-2025, 12:40 AM by trandoductin.)
But the I wrote my python code based on GEGL code as seen below
static void process_rgba (GeglOperation *op, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (op); gfloat *in_pixel; gfloat *out_pixel; gfloat black_level = (gfloat) o->black_level; gfloat diff; gfloat exposure_negated = (gfloat) -o->exposure; gfloat gain; gfloat white; glong i; in_pixel = in_buf; out_pixel = out_buf; white = exp2f (exposure_negated); diff = MAX (white - black_level, 0.000001); gain = 1.0f / diff; for (i=0; i<n_pixels; i++) { out_pixel[0] = (in_pixel[0] - black_level) * gain; out_pixel[1] = (in_pixel[1] - black_level) * gain; out_pixel[2] = (in_pixel[2] - black_level) * gain; out_pixel[3] = in_pixel[3]; out_pixel += 4; in_pixel += 4; } } Hackathon, Ran my function on a layer and delete half of it. Then ran exposure on the original other half and see how much darker it is. So I used simulate_gimp_exposure(image,layer,0.002,1.696/2.05) #dividing 2.1-ish or 2.05 to match for specific 1.696 exposure. pretty close I hope it's good enough for my client
02-14-2025, 09:14 AM
(02-14-2025, 12:17 AM)trandoductin Wrote: But the I wrote my python code based on GEGL code as seen below GEGL works on linear values. Nowhere in the code you show does it say that the 0.0 .. 1.0 values are gamma-corrected. Using the spreadsheet functions from the tutorial I linked, I get Gimp's results if I convert to linear first.
02-16-2025, 09:15 AM
Why not use the GEGL filter. One of your other posts here. https://www.gimp-forum.net/Thread-GEGL-k...9#pid41869
(02-16-2025, 03:10 AM)trandoductin Wrote: Ok this is above my head Did you read the tutorial I linked to?
02-16-2025, 10:23 AM
Yeah skimmed it over and something about gamma but their is no gamma in GEGL code that I can see
|
« Next Oldest | Next Newest »
|