def _create_test_image(): image = pdb.gimp_image_new(100, 100, gimpenums.RGB) layers = [ pdb.gimp_layer_new(image, 50, 20, gimpenums.RGBA_IMAGE, "Layer 1", 100.0, gimpenums.NORMAL_MODE), pdb.gimp_layer_new(image, 10, 10, gimpenums.RGBA_IMAGE, "Layer 2", 50.0, gimpenums.DISSOLVE_MODE), ] channels = [ pdb.gimp_channel_new(image, 100, 100, "Channel 1", 100.0, gimpcolor.RGB(0, 0, 0)), pdb.gimp_channel_new(image, 100, 100, "Channel 2", 50.0, gimpcolor.RGB(1, 0, 0)), ] vectors_list = [ pdb.gimp_vectors_new(image, "Vectors 1"), pdb.gimp_vectors_new(image, "Vectors 2"), ] for layer, channel, vectors in reversed( list(zip(layers, channels, vectors_list))): pdb.gimp_image_insert_layer(image, layer, None, 0) pdb.gimp_image_insert_channel(image, channel, None, 0) pdb.gimp_image_insert_vectors(image, vectors, None, 0) return image
def __init__(self, default=gimpcolor.RGB(1.0, 0, 0)): if isinstance(default, gimpcolor.RGB): color = default elif isinstance(default, tuple): color = apply(gimpcolor.RGB, default) ColorButton.__init__(self, _("Python-Fu Color Selection"), 100, 20, color, COLOR_AREA_FLAT)
def completion(infilepath, mask_filepath, outfilepath): # since some tests use the same input file, cat the testname to make an outfilename # out and reference have same name, different directories # open test file try: image = pdb.gimp_file_load(infilepath, infilepath, run_mode=RUN_NONINTERACTIVE) drawable = pdb.gimp_image_get_active_layer(image) mask = pdb.gimp_file_load_layer(image, mask_filepath) pdb.gimp_image_add_layer(image, mask, 0) pdb.gimp_image_select_color(image, CHANNEL_OP_REPLACE, mask, gimpcolor.RGB(255, 255, 255)) pdb.gimp_image_remove_layer(image, mask) # if select is not None: # # Make selection x,y, width, height # # pdb.gimp_rect_select(image, 100, 90, 100, 50, 0, False, 0) # pdb.gimp_rect_select(image, select[0], select[1], select[2], select[3], 0, False, 0) except: print("IMPROPER preprocessing") return # Invoke the test # Formerly: eval(teststring) but eval only takes expressions, not statements start = time.time() try: # exec teststring pdb.python_fu_heal_selection(image, drawable, 50, 1, 1, run_mode=RUN_NONINTERACTIVE) except RuntimeError: print("EXCEPTION") return print("Completion time: " + str(time.time() - start)) # test post processing try: # !!! Refresh drawable in case the plugin returned a new image drawable = pdb.gimp_image_get_active_drawable(image) # Save altered or new image in a temp directory. # !!! Why do you need to pass drawable, doesn't it save all the layers? This bit me. if pdb.gimp_drawable_has_alpha(drawable): pdb.gimp_image_flatten(image) # Since saving ppm, get rid of alpha drawable = pdb.gimp_image_get_active_drawable(image) pdb.gimp_file_save(image, drawable, outfilepath, outfilepath, run_mode=RUN_NONINTERACTIVE) pdb.gimp_image_delete(image) except: print("IMPROPER post processing") return
def generateOnionLayer(self, onionLayer, layerName, textureAtlases, textureIdx): pdb.gimp_image_undo_freeze(self.img) try: #Save active layer activeLayer=pdb.gimp_image_get_active_layer(self.img) #Save selection origSelectionChan=pdb.gimp_selection_save(self.img) #delete old layer if self.layer_exists(onionLayer): self.img.remove_layer(onionLayer) #generate layer #( image, # width, # height, # Type { RGB-IMAGE (0), RGBA-IMAGE (1), GRAY-IMAGE (2), GRAYA-IMAGE (3), INDEXED-IMAGE (4), INDEXEDA-IMAGE (5) }, # layer Name, # The layer opacity (0 <= opacity <= 100), """ The layer combination mode { LAYER-MODE-NORMAL-LEGACY (0), LAYER-MODE-DISSOLVE (1), LAYER-MODE-BEHIND-LEGACY (2), LAYER-MODE-MULTIPLY-LEGACY (3), LAYER-MODE-SCREEN-LEGACY (4), LAYER-MODE-OVERLAY-LEGACY (5), LAYER-MODE-DIFFERENCE-LEGACY (6), LAYER-MODE-ADDITION-LEGACY (7), LAYER-MODE-SUBTRACT-LEGACY (8), LAYER-MODE-DARKEN-ONLY-LEGACY (9), LAYER-MODE-LIGHTEN-ONLY-LEGACY (10), LAYER-MODE-HSV-HUE-LEGACY (11), LAYER-MODE-HSV-SATURATION-LEGACY (12), LAYER-MODE-HSL-COLOR-LEGACY (13), LAYER-MODE-HSV-VALUE-LEGACY (14), LAYER-MODE-DIVIDE-LEGACY (15), LAYER-MODE-DODGE-LEGACY (16), LAYER-MODE-BURN-LEGACY (17), LAYER-MODE-HARDLIGHT-LEGACY (18), LAYER-MODE-SOFTLIGHT-LEGACY (19), LAYER-MODE-GRAIN-EXTRACT-LEGACY (20), LAYER-MODE-GRAIN-MERGE-LEGACY (21), LAYER-MODE-COLOR-ERASE-LEGACY (22), LAYER-MODE-OVERLAY (23), LAYER-MODE-LCH-HUE (24), LAYER-MODE-LCH-CHROMA (25), LAYER-MODE-LCH-COLOR (26), LAYER-MODE-LCH-LIGHTNESS (27), LAYER-MODE-NORMAL (28), LAYER-MODE-BEHIND (29), LAYER-MODE-MULTIPLY (30), LAYER-MODE-SCREEN (31), LAYER-MODE-DIFFERENCE (32), LAYER-MODE-ADDITION (33), LAYER-MODE-SUBTRACT (34), LAYER-MODE-DARKEN-ONLY (35), LAYER-MODE-LIGHTEN-ONLY (36), LAYER-MODE-HSV-HUE (37), LAYER-MODE-HSV-SATURATION (38), LAYER-MODE-HSL-COLOR (39), LAYER-MODE-HSV-VALUE (40), LAYER-MODE-DIVIDE (41), LAYER-MODE-DODGE (42), LAYER-MODE-BURN (43), LAYER-MODE-HARDLIGHT (44), LAYER-MODE-SOFTLIGHT (45), LAYER-MODE-GRAIN-EXTRACT (46), LAYER-MODE-GRAIN-MERGE (47), LAYER-MODE-VIVID-LIGHT (48), LAYER-MODE-PIN-LIGHT (49), LAYER-MODE-LINEAR-LIGHT (50), LAYER-MODE-HARD-MIX (51), LAYER-MODE-EXCLUSION (52), LAYER-MODE-LINEAR-BURN (53), LAYER-MODE-LUMA-DARKEN-ONLY (54), LAYER-MODE-LUMA-LIGHTEN-ONLY (55), LAYER-MODE-LUMINANCE (56), LAYER-MODE-COLOR-ERASE (57), LAYER-MODE-ERASE (58), LAYER-MODE-MERGE (59), LAYER-MODE-SPLIT (60), LAYER-MODE-PASS-THROUGH (61), LAYER-MODE-REPLACE (62), LAYER-MODE-ANTI-ERASE (63) }) """ #(image, image width, image height, RGB-Image, "Preview Onion Layer", 100% full Opacity, Normal Mode) onionLayer = pdb.gimp_layer_new(self.img, self.img.width, self.img.height, 1, layerName, 50.0, 28) pdb.gimp_image_insert_layer(self.img, onionLayer, None,0) ##Read Each subtexture and convert to a rectangle texture=textureAtlases[textureIdx] bngColor = pdb.gimp_context_get_background() for key in texture.subtextures: for subtexture in texture.subtextures[key]: #Replace Selection pdb.gimp_selection_none(self.img) selection=pdb.gimp_image_select_rectangle(self.img, 2, int(subtexture.xy[0]), int(subtexture.xy[1]), int(subtexture.size[0]), int(subtexture.size[1])) fillColor=gimpcolor.RGB(random.randrange(0, 255),random.randrange(0, 255),random.randrange(0, 255)) pdb.gimp_context_set_background(fillColor) pdb.gimp_drawable_edit_fill(onionLayer, 1) pdb.gimp_selection_none(self.img) #Restore gimp original state pdb.gimp_context_set_background(bngColor) pdb.gimp_image_set_active_layer(self.img, activeLayer) pdb.gimp_image_select_item(self.img, 2, origSelectionChan) self.img.remove_channel(origSelectionChan) except Exception as exp: error_box(traceback.format_exc()) error_box("Exception: "+str(exp)) #Update Gimp GUI gimp.displays_flush() pdb.gimp_image_undo_thaw(self.img) return onionLayer
def z0(img, layer): bas = img.layers[-1] layers = [ pdb.gimp_layer_new(img, SZ, SZ, RGB_IMAGE, "base", 100, NORMAL_MODE), pdb.gimp_layer_new(img, SZ, SZ, RGB_IMAGE, "base", 100, NORMAL_MODE), ] for l in layers: pdb.gimp_layer_add_alpha(l) pdb.gimp_image_add_layer(img, l, 0) drw = pdb.gimp_image_get_active_drawable(img) pdb.gimp_context_set_background(gimpcolor.RGB(255, 0, 0)) pdb.gimp_drawable_fill(drw, FILL_BACKGROUND) copypaste(img, drw, img, bas, [400, 400], [0, 0], [128, 128])
def generate_otc_bitmap_font(image, drawable, font, font_size, border, antialias, outputfolder): if not outputfolder: pdb.gimp_message('You need to select correct output folder.') return # automated glyphs size getting temp_image = gimp.Image(300, 300, RGB) test_layer = pdb.gimp_text_fontname(temp_image, None, 0, 0, chr(137).decode('cp1252'), border, antialias, font_size, PIXELS, font) glyph_width = test_layer.width + (int(border) * 2) temp_image.remove_layer(test_layer) test_layer = pdb.gimp_text_fontname(temp_image, None, 0, 0, chr(138).decode('cp1252'), border, antialias, font_size, PIXELS, font) glyph_height = test_layer.height + (int(border) * 2) temp_image.remove_layer(test_layer) gimp.pdb.gimp_image_delete(temp_image) #pdb.gimp_message(str(int(round(glyph_width))) + ' ' + str(int(round(glyph_height)))) # actual making glyph char_begin = 32 # space is always first char_end = 256 num_chars = char_end - char_begin width = int(glyph_width) * 16 num_lines = num_chars / 16 if num_chars % 16 > 0: num_lines += 1 height = int(glyph_height) * num_lines if border > 0: width += (int(border) * 2) height += (int(border) * 2) image = gimp.Image(width, height, RGB) image.disable_undo() gimp.set_foreground(255, 255, 255) gimp.set_background(0, 0, 0) glyphs_layer = gimp.Layer(image, "Glyphs", width, height, RGBA_IMAGE, 100, NORMAL_MODE) image.add_layer(glyphs_layer, 0) disp = gimp.Display(image) for i in range(char_begin, char_end): if i == 127 or i == 129 or (i >= 141 and i <= 144) or i == 157: string = u"\u25A1" else: string = chr(i).decode('cp1252') offset = i - char_begin x_pos = (offset % 16) * int(glyph_width) y_pos = ((offset / 16) * int(glyph_height)) if border > 0: border_layer = gimp.Layer(image, "border" + str(i), width, height, RGBA_IMAGE, 100, NORMAL_MODE) image.add_layer(border_layer, 0) text_layer = pdb.gimp_text_fontname(image, None, x_pos, y_pos, string, border, antialias, font_size, PIXELS, font) if border > 0: pdb.gimp_image_select_color(image, CHANNEL_OP_REPLACE, text_layer, gimpcolor.RGB(255, 255, 255)) pdb.gimp_selection_grow(image, border) pdb.gimp_bucket_fill(border_layer, 1, 0, 100, 1.0, True, 0, 0) #pdb.gimp_edit_fill(text_layer, BACKGROUND_FILL) #pdb.gimp_drawable_edit_fill(text_layer, BACKGROUND_FILL) #add_text_outline(image, text_layer) gimp.progress_update(float(offset) / float(num_chars)) image.merge_visible_layers(CLIP_TO_IMAGE) image.enable_undo() # save everything fontText = str(font) + '-' + str(int(round(font_size))) + 'px' if antialias: fontText = fontText + '-antialiased' if border: fontText = fontText + '-bordered' f = open(outputfolder + '/' + fontText + '.otfont', "w") f.write('Font\n name: ' + fontText + '\n texture: ' + fontText + '\n height: ' + str(int(round(glyph_height))) + '\n glyph-size: ' + str(int(round(glyph_width))) + ' ' + str(int(round(glyph_height))) + '\n space-width: 4\n') f.close() pdb.gimp_file_save(image, image.layers[0], outputfolder + '/' + fontText + '.png', '?')
def stringToColor(self, string): colorlist = string[5:-1].split(", ") return gimpcolor.RGB(float(colorlist[0]), float(colorlist[1]), float(colorlist[2]), float(colorlist[3]))
def remap_hue(self): #input can be RGB or RGBA bpp = self.drawable.bpp (bx1, by1, bx2, by2) = self.drawable.mask_bounds bw = bx2 - bx1 bh = by2 - by1 #input layer offset (ox, oy) = self.drawable.offsets src_rgn = self.drawable.get_pixel_rgn(bx1, by1, bw, bh, False, False) #all the input pixels in one huge array #src_rgn[...] returns a packed byte array as a string #we unpack this string using python array src_pixels = array.array("B", src_rgn[bx1:bx2, by1:by2]) #delete existing preview layer self.layer_destroy() #create new output layer self.layer = gimp.Layer(self.image, "Hue map", bw, bh, RGBA_IMAGE, 100, NORMAL_MODE) #set correct position self.layer.set_offsets(bx1 + ox, by1 + oy) dest_rgn = self.layer.get_pixel_rgn(0, 0, bw, bh, True, True) #all the output pixels dest_pixels = array.array("B", dest_rgn[0:bw, 0:bh]) #output is always RGBA dest_bpp = 4 #add layer into image self.image.add_layer(self.layer, 0) #for 8bit RGB, the hue resolution is 6*256 = 1536 #sampling in lower resolution (like 360°) would result in color loss #we pre-sample the gradient instead of sampling it on each pixel #it results in better performance on larger selections (> 39x39 px) num_samples = 6 * 256 hue_samples = pdb.gimp_gradient_get_uniform_samples( self.gradient_button.get_gradient(), num_samples + 1, False)[1] hues = [None] * num_samples for i in range(0, num_samples): #convert rgb into hue sample_rgb = gimpcolor.RGB(hue_samples[i * 4 + 0], hue_samples[i * 4 + 1], hue_samples[i * 4 + 2], hue_samples[i * 4 + 3]) hues[i] = sample_rgb.to_hsv().h #start a progress bar gimp.progress_init("Hue map") for y in range(0, bh): for x in range(0, bw): pos = (x + bw * y) * bpp #read a pixel as a 3 or 4 byte array c_array = src_pixels[pos:(pos + bpp)] #create a RGB struct, if there is no alpha, set it to 100% c_rgb = gimpcolor.RGB(c_array[0], c_array[1], c_array[2], c_array[3] if bpp == 4 else 255) #RGB -> HSV c_hsv = c_rgb.to_hsv() #calculate index into hue replacement array hue_index = int(round(c_hsv.h * num_samples)) #replace hue c_hsv.h = hues[hue_index] #HSV -> RGB c_rgb = c_hsv.to_rgb() #RGB -> byte array c_array[0:dest_bpp] = array.array("B", c_rgb[0:dest_bpp]) dest_pos = (x + bw * y) * dest_bpp #write a pixel into the output array dest_pixels[dest_pos:(dest_pos + dest_bpp)] = c_array #update the progress bar gimp.progress_update(float(y + 1) / bh) #write the output pixel array into the output layer dest_rgn[0:bw, 0:bh] = dest_pixels.tostring() #apply changes self.layer.flush() #apply selection mask self.layer.merge_shadow(True) #refresh self.layer.update(0, 0, bw, bh) #refresh gimp.displays_flush()
#!/usr/bin/env python # GIMP Python import time import gimp import gimpcolor from gimpfu import * map_palette = [ [gimpcolor.RGB(0.49019607843137253, 0.6901960784313725, 0.21568627450980393, 1.0), "GRASS Up"], [gimpcolor.RGB(0.4235294117647059, 0.592156862745098, 0.1843137254901961, 1.0), "GRASS Flat"], [gimpcolor.RGB(0.34509803921568627, 0.48627450980392156, 0.15294117647058825, 1.0), "GRASS Down"], [gimpcolor.RGB(0.9568627450980391, 0.9019607843137255, 0.6313725490196078, 1.0), "SAND Up"], [gimpcolor.RGB(0.8235294117647058, 0.7803921568627451, 0.5411764705882353, 1.0), "SAND Flat"], [gimpcolor.RGB(0.6745098039215687, 0.6352941176470588, 0.44705882352941173, 1.0), "SAND Down"], [gimpcolor.RGB(0.7725490196078432, 0.7725490196078432, 0.7725490196078432, 1.0), "WOOL Up"], [gimpcolor.RGB(0.6627450980392157, 0.6627450980392157, 0.6627450980392157, 1.0), "WOOL Flat"], [gimpcolor.RGB(0.5411764705882353, 0.5411764705882353, 0.5411764705882353, 1.0), "WOOL Down"], [gimpcolor.RGB(0.9882352941176471, 0.0, 0.0, 1.0), "FIRE Up"], [gimpcolor.RGB(0.8509803921568627, 0.0, 0.0, 1.0), "FIRE Flat"], [gimpcolor.RGB(0.6980392156862745, 0.0, 0.0, 1.0), "FIRE Down"], [gimpcolor.RGB(0.6196078431372549, 0.6196078431372549, 0.9882352941176471, 1.0), "ICE Up"], [gimpcolor.RGB(0.5333333333333333, 0.5333333333333333, 0.8509803921568627, 1.0), "ICE Flat"], [gimpcolor.RGB(0.43529411764705883, 0.43529411764705883, 0.6980392156862745, 1.0), "ICE Down"], [gimpcolor.RGB(0.6470588235294118, 0.6470588235294118, 0.6470588235294118, 1.0), "METAL Up"],
def get_value(self): (r,g,b) = self.gdk_to_gimp(self.picker.get_color()) return gimpcolor.RGB(r,g,b)