Pocholo
Pocholo

Reputation: 1

Can someone help me with "pdb.gimp_drawable_set_pixel"?

I been learning GIMP python for about a year or so and I'm stuck on how to translate from GIMP scheme to GIMP python. I have an old GIMP scm from the creators "T. Demand & GnuTux" that creates a Starry sky that I'm trying to translate to python. So far the code is giving me an error "pdb.gimp_drawable_set_pixel(layer_one, xs, ys, 3, [pixel]) TypeError: wrong parameter type"

Can anybody fix this and give me an idea what I'm doing wrong? Thank you in advance!

Here is the whole code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import *
import os, sys,time 
import random
import math
import gettext
gettext.install("gimp20", gimp.locale_directory, unicode=True)

def pm_create_starry_night(img, drawable, smStars, bgLum):
          
    #--- Initiates the temporary state
    pdb.gimp_context_set_defaults()
    pdb.gimp_context_set_default_colors()
    
    # --- Star group
    img.undo_group_start()   
    
    ii = 0
    ns = 0
    xs = 0
    ys = 0
    lum = 0
    pixel = "Bytesarray"
    width = pdb.gimp_drawable_width(drawable)      # Get Width 
    height = pdb.gimp_drawable_height(drawable)      # Get Height
    
    random.random = "realtime"
    pixel = [0, 255]
    pixel = [1, 255]
    pixel = [2, 255]
     
    # --- Create the sky 
    layer_one = pdb.gimp_layer_new(img, img.width, img.height, RGBA_IMAGE, "smStars", 100, LAYER_MODE_NORMAL)
    pdb.gimp_image_insert_layer(img, layer_one, None, -1)
    pdb.gimp_layer_add_alpha(layer_one)
    pdb.gimp_context_set_foreground((255, 255, 255))
    pdb.gimp_context_set_background((0, 0, 0))   
    pdb.gimp_drawable_fill(layer_one, FILL_BACKGROUND)
  
    # --- Generating small stars
    pdb.gimp_context_set_foreground((255, 255, 255)) 
    while ns  < smStars:   
        ns = ns + 1
        xs = (random.random, (width -1))
        ys = (random.random, (height -1))
        lum = (random.random, (200 + 128))
        pixel = 0, (lum, (random.random), + 64)
        pixel = 1, (lum, (random.random), + 64)
        pixel = 2, (lum, (random.random), + 64)
        pdb.gimp_drawable_set_pixel(layer_one, xs, ys, 3, [pixel])

        ii = ii + 1
        if ii > 10000:
            ns = smStars

    pdb.gimp_displays_flush()
        
    # --- Set gimp to default
    pdb.gimp_context_set_defaults()
    pdb.gimp_context_set_default_colors()
    
    # --- End group       
    img.undo_group_end()
    
register(
    "pm_create_starry_night",
    "Creates stars at night",
    "Creates stars at night effect",
    "Pocholo",
    "Pocholo",
    "2021",
    "Create a Starry night",
    "RGB*",
    [    
    (PF_IMAGE, "img", "Input image", 0),
    (PF_DRAWABLE, "drawable", "Input layer", 0),
    (PF_ADJUSTMENT, "smStars", "Small stars", 500, (50, 10000, 10)),
    (PF_ADJUSTMENT, "bgLum", "Background luminosity", 5, (0, 64, 1)),
    ],
    [],
    pm_create_starry_night, menu="<Image>/Pocholo-scripts/Create a Starry night",
    domain=("gimp20", gimp.locale_directory))
main()                                      




Starry sky.scm

```(define (script-fu-starry-night-sample image drawable smalls bglum)

  (let* (
      (layer-one -1)      
      (ii 0)
      (ns 0)
      (xs 0)
      (ys 0)     
      (lum 0)
      (pixw (cons-array 3 'byte))
      (height (car (gimp-drawable-height drawable)))     ; Get Height 
      (width (car (gimp-drawable-width drawable)))       ; Get Width
    )

    (srand (realtime))
    (aset pixw 0 255)
    (aset pixw 1 255)
    (aset pixw 2 255)
   

    ; Set the fg to white, bg to black
    (gimp-palette-set-foreground '(255 255 255))
    (gimp-context-set-background '(0 0 0))
    (set! layer-one (car (gimp-layer-new image width height RGB-IMAGE "Bottom" 100 LAYER-MODE-NORMAL-LEGACY)))
    (gimp-image-add-layer image layer-one -1)
    (gimp-image-lower-layer-to-bottom image layer-one)

    (gimp-drawable-fill layer-one 1)  ;0 FG, 1 BG, 2 white

    ; generating small stars
    (while (< ns smalls)
      (set! ns (+ ns 1))
      (set! xs (rand (- width 1)))
      (set! ys (rand (- height 1)))
      (set! lum (+ (rand 200) 128))
      (aset pixw 0 (+ lum (rand 64)))
      (aset pixw 1 (+ lum (rand 64)))
      (aset pixw 2 (+ lum (rand 64)))
      (gimp-drawable-set-pixel layer-one xs ys 3 pixw)
      
      
      
      
      
      ; preparing the exit of the loop
      (set! ii (+ ii 1))
      (if (> ii 10000) (set! ns smalls))
    ) ; end of loop   

Upvotes: 0

Views: 506

Answers (1)

xenoid
xenoid

Reputation: 8914

With

pixel = 2, (lum, (random.random), + 64)

You are setting pixel to a tuple structure that looks like:

(number, ( number, function, number))

Where function is a function object, not a result. You then put brackets around it, so you are passing a list of such things. What is required is an array of integers in the [0-255] range. For instance to set the top corner to red:

pdb.gimp_drawable_set_pixel(layer,0,0,4,[255,0,0,255])

And note that this is 4,[255,0,0,255] because since you added an alpha channel there are 4 values to provide.

On a general note, your "python" code is still full of things that make sense only in Scheme (see definitions of xs, ys and lum), and the script you are starting with is not very good:

  • Since the layer is created with type RGBA_IMAGE it has an alpha channel from the start, no need to add one.
  • Re-setting everything to defaults when leaving is a capital sin, use gimp.context_push() on entry to your script and gimp.context_pop() on exit.
  • And since pdb.gimp_context_set_defaults() also resets the colors there is no need for the following pdb.gimp_context_set_default_colors().
  • Having this side ii variable to control the maximum iterations of the loop is the most WTF code I have seen in a while. In Python you would do for _ in range(min(smStars,10000)) (the is a varaible fir the loop index, using` is a convention to indicate that you are not using it anywhere).

Futhermore, the set_pixel() operations are slow, in python-fu you can use "pixel regions". These are Python arrays directly mapped to the pixel data and are very efficient.

Last, this whole script can be done in a few operations:

  • Create a layer filled with black
  • Create a layer filled with middle gray (127,127,127) on top of it
  • Filters > Noise > RGB noise or Filters > Noise > HSV noise to alter the gray layer
  • Set gray layer to Dissolve mode
  • Set gray layer opacity to taste

enter image description here

Of course for astronomical accuracy you need to further restrict colors: you can't have green or purple, and even the blues are mere tints on the brighter stars.

Upvotes: 2

Related Questions