Reputation: 1
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
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:
gimp.context_push()
on entry to your script and gimp.context_pop() on exit.pdb.gimp_context_set_defaults()
also resets the colors there is no need for the following pdb.gimp_context_set_default_colors()
.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:
Filters > Noise > RGB noise
or Filters > Noise > HSV noise
to alter the gray layerDissolve
modeOf 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