def cree_background(inLayer, inLayerF, Img): """Add background to inLayer""" newlayer = pdb.gimp_layer_copy(inLayer, True) newfond = pdb.gimp_layer_copy(inLayerF, True) layername = pdb.gimp_item_get_name(inLayer) pdb.gimp_item_set_visible(newlayer, True) pdb.gimp_image_insert_layer(Img, newlayer, None, 0) pdb.gimp_image_set_active_layer(Img, inLayer) pdb.gimp_image_insert_layer(Img, newfond, None, -1) pdb.gimp_image_lower_item(Img, newfond) pdb.gimp_item_set_visible(newfond, 1) pdb.gimp_context_set_sample_transparent(True) pdb.gimp_image_select_contiguous_color(Img, CHANNEL_OP_REPLACE, newlayer, 10, 10) pdb.gimp_edit_clear(newfond) pdb.gimp_item_set_visible(inLayer, True) clipped_layer = pdb.gimp_image_merge_down(Img, inLayer, CLIP_TO_IMAGE) pdb.gimp_item_set_name(clipped_layer, layername) pdb.gimp_selection_invert(Img) pdb.gimp_context_set_foreground((117, 117, 154)) pdb.gimp_edit_fill(newlayer, FILL_FOREGROUND) floating_sel = pdb.gimp_edit_paste(newlayer, 0) pdb.gimp_layer_set_opacity(floating_sel, 70) pdb.gimp_floating_sel_anchor(floating_sel) pdb.gimp_layer_set_opacity(newlayer, 85) pdb.gimp_selection_none(Img) layerfinal = pdb.gimp_image_get_layer_by_name(Img, layername) pdb.gimp_item_set_visible(layerfinal, False)
def on_add(self, widget, copy=False): """ Add new layer to the image and a new frame to the Timeline. if copy is true them the current layer will be copy. """ # starting gimp undo group self.image.undo_group_start() name = "Frame " + str(len(self.frames)) # create the layer to add l = None if not copy: l = gimp.Layer(self.image, name, self.image.width, self.image.height, RGBA_IMAGE, 100, NORMAL_MODE) else: # copy current layer to add l = self.frames[self.active].layer.copy() l.name = name # adding layer self.image.add_layer(l, len(self.image.layers) - self.active - 1) if self.new_layer_type == TRANSPARENT_FILL and not copy: pdb.gimp_edit_clear(l) self._scan_image_layers() self.on_goto(None, NEXT, True) if len(self.frames) == 1: self._toggle_enable_buttons(NO_FRAMES) # ending gimp undo group self.image.undo_group_end()
def load_caches(args): inColorFondR, inColorFondG, inColorFondB, outDir = args.split(" ") inDir, inNameLayerFleche = GRAPH_PATH + "layers/", "layer_fleche-1.png" inColorFondR, inColorFondG, inColorFondB = int(inColorFondR), int( inColorFondG), int(inColorFondB) nb, listimg = pdb.file_glob(inDir + "*.png", 1) baseimage = pdb.gimp_image_new(10, 10, RGB) fondcolor = (inColorFondR, inColorFondG, inColorFondB) for filename in listimg: layer = pdb.gimp_file_load_layer(baseimage, filename) pdb.gimp_image_insert_layer(baseimage, layer, None, 0) pdb.gimp_image_resize_to_layers(baseimage) pdb.gimp_message("Layers chargés") pdb.gimp_selection_all(baseimage) layerfond = pdb.gimp_image_get_layers(baseimage)[1][0] layerfond = gimp.Item.from_id(layerfond) fond = pdb.gimp_layer_copy(layerfond, 1) _, _, _, xmax, ymax = pdb.gimp_selection_bounds(baseimage) pdb.gimp_item_set_name(fond, "layer_fond.png") pdb.gimp_image_insert_layer(baseimage, fond, None, 0) pdb.gimp_edit_clear(fond) pdb.gimp_image_select_round_rectangle(baseimage, CHANNEL_OP_REPLACE, 0, 0, xmax, ymax, 35, 35) pdb.gimp_selection_shrink(baseimage, 3) pdb.gimp_selection_feather(baseimage, 20) pdb.gimp_context_set_foreground(fondcolor) pdb.gimp_edit_fill(fond, FILL_FOREGROUND) pdb.gimp_image_lower_item_to_bottom(baseimage, fond) pdb.plug_in_hsv_noise(baseimage, fond, 5, 38, 63, 74) pdb.gimp_selection_none(baseimage) pdb.gimp_message("Fond créé") caches(baseimage, inNameLayerFleche, "layer_fond.png") pdb.gimp_message("Cache créé") layercache = pdb.gimp_image_get_layer_by_name(baseimage, "cache.png") layerfond = pdb.gimp_image_get_layer_by_name(baseimage, "layer_fond.png") layerfleche = pdb.gimp_image_get_layer_by_name(baseimage, inNameLayerFleche) pdb.gimp_item_set_visible(layerfond, True) pdb.gimp_image_merge_down(baseimage, layercache, CLIP_TO_IMAGE) pdb.gimp_item_set_visible(layerfleche, True) pdb.gimp_image_merge_down(baseimage, layerfleche, CLIP_TO_IMAGE) pdb.gimp_image_scale(baseimage, 900, 550) # drawable = pdb.gimp_image_get_active_drawable(baseimage) pdb.script_fu_multiple_layer_actions(baseimage, None, 0, 0, (0, 0, 0), 4, 0, 0, 0, 0, 0) pdb.gimp_message("Taille de l'image ajustée") pdb.script_fu_export_layers(baseimage, None, outDir, "~l") pdb.gimp_message("Layers enregistrés")
def clear_background(image, drawable): # invert selection, thus selecting the background pdb.gimp_selection_invert(image) # clear background pdb.gimp_edit_clear(drawable) # invert selection pdb.gimp_selection_invert(image)
def MDFade(image, layer, srcmode, dstmode, fademode): srclut = SelectSrcLUT(srcmode) dstlut = SelectDstLUT(dstmode) gimp.progress_init("Generating palette fade...") pdb.gimp_image_undo_group_start(image) # Get the layer position. pos = FindLayer(image, layer) srcWhite = FindColor(255, srcmode) if (fademode == FadeMode.CurrentToBlack): conv = lambda jj, ss: (jj * (15 - ss)) // 15 elif (fademode == FadeMode.BlackToCurrent): conv = lambda jj, ss: (jj * ss) // 15 elif (fademode == FadeMode.CurrentToWhite): conv = lambda jj, ss: (jj * (15 - ss) + srcWhite * ss) // 15 else: #if (fademode == FadeMode.WhiteToCurrent): conv = lambda jj, ss: (jj * ss + srcWhite * (15 - ss)) // 15 finalLayer = None for step in xrange(15): lut = { chr(ii): chr(dstlut[srclut[conv(ii, step)]]) for ii in xrange(256) } # Create a new layer to save the results (otherwise is not possible to undo the operation). newLayer = layer.copy() image.add_layer(newLayer, pos) # Clear the new layer. pdb.gimp_edit_clear(newLayer) newLayer.flush() # Calculate the number of tiles. tile_width = gimp.tile_width() tile_height = gimp.tile_height() # Ceiling division width_tiles = -(-layer.width // tile_width) height_tiles = -(-layer.height // tile_height) # Iterate over the tiles. for col in xrange(width_tiles): for row in xrange(height_tiles): # Update the progress bar. gimp.progress_update( float(step * width_tiles * height_tiles + col * height_tiles + row) / float(15 * width_tiles * height_tiles)) ConvertTileNoSHL(layer.get_tile(False, row, col), newLayer.get_tile(False, row, col), lut) # Update the new layer. newLayer.flush() newLayer.merge_shadow(True) newLayer.update(0, 0, layer.width, layer.height) finalLayer = newLayer # Remove the old layer. if finalLayer is not None: layerName = layer.name image.remove_layer(layer) finalLayer.name = layerName gimp.displays_flush() pdb.gimp_image_undo_group_end(image)
def nobox(image=None): if not image: image = gimp.image_list()[0] pdb.gimp_context_set_sample_transparent(True) image_size = (image.width, image.height) for layer in image.layers: if not pdb.gimp_drawable_has_alpha(layer): layer.add_alpha() if layer.offsets != (0, 0) or (layer.width, layer.height) != image_size: pdb.gimp_layer_resize_to_image_size(layer) (xmax, ymax) = (image.width - 1, image.height - 1) for (x, y) in [(0, 0), (xmax, 0), (0, ymax), (xmax, ymax)]: _num_channels, pixel = pdb.gimp_drawable_get_pixel(layer, x, y) if all(p > 240 for p in pixel): pdb.gimp_image_select_contiguous_color(image, 2, layer, x, y) pdb.gimp_edit_clear(layer)
def cookie_cutter_letter(img, substrate, right, font, letter): '''Cut text shaped like letter out of the given layer.''' temp_layer = gpdb.gimp_text_fontname(img, substrate, right, 0, letter, 1, False, FONT_HEIGHT, PIXELS, font) gpdb.gimp_selection_layer_alpha(temp_layer) angle = random.uniform(*ANGLE_RANGE) xaxis = right yaxis = 15 # srcX = float(xaxis) # dstX = float(srcX + random.uniform(0, 25)) # srcY = float(yaxis) # dstY = float(srcY + random.uniform(0, 25)) # scaleX = scaleY = float(100) # We need to save the selection as a channel so we can mess with # the letter form. shape = gpdb.gimp_selection_save(img) gpdb.gimp_selection_none(img) gpdb.gimp_floating_sel_remove(temp_layer) # Distort the form of the individual letter: shape = gpdb.gimp_item_transform_rotate(shape, angle, 0, xaxis, yaxis) # We aren't doing any letter warping now, but if we were, this is the # point where it should be done. We want to warp the shape of textLayer, # which later serves as a cutout for the dark noise layer. If we warp the # dark noise layer directly we will end up with warped dots. # # gpdb.gimp_context_set_transform_resize(TRANSFORM_RESIZE_CROP) # shape = gpdb.gimp_item_transform_2d(shape, srcX, srcY, angle, # scaleX, scaleY, dstX, dstY) gpdb.gimp_selection_load(shape) img.remove_channel(shape) # Note the bounding box of the letter form so we can figure out # where the next one should go. bounds = gpdb.gimp_selection_bounds(img) new_right = bounds[3] + LETTER_SPACING # Actually cut the letter form out of the substate. gpdb.gimp_selection_invert(img) gpdb.gimp_edit_clear(substrate) gpdb.gimp_selection_none(img) return new_right
def change_num(image, inNumero): layer = pdb.gimp_image_get_active_layer(image) pdb.gimp_context_set_sample_transparent(True) pdb.gimp_image_select_contiguous_color(image, CHANNEL_OP_REPLACE,layer, 1, 1) pdb.gimp_selection_invert(image) _, x, y, x2, y2 = pdb.gimp_selection_bounds(image) xthird=x + ((x2 - x) // 4 * 3) y = _find_black_not_transparent(image, layer, xthird, y) pdb.gimp_context_set_sample_transparent(False) pdb.gimp_image_select_contiguous_color(image, CHANNEL_OP_REPLACE, layer, xthird, y) pdb.gimp_edit_clear(layer) if inNumero > 1: _, x, y, x2, y2 = pdb.gimp_selection_bounds(image) ymiddle = y + ( (y2 - y) // 2) keep = True while keep: if not _is_transparent(image, layer, x, ymiddle): keep = False pdb.gimp_context_set_sample_transparent(False) pdb.gimp_context_set_sample_threshold(1) pdb.gimp_image_select_contiguous_color(image, CHANNEL_OP_REPLACE, layer, x+1, ymiddle) pdb.gimp_context_set_sample_threshold(0.1) x += 1 pdb.gimp_edit_clear(layer) _, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image) pdb.gimp_image_select_rectangle(image, CHANNEL_OP_REPLACE, x1, y1, x2-x1, y2-y1) filename = GRAPH_PATH + str(inNumero) + ".png" imagechiffre = pdb.gimp_file_load(filename, filename) layerchiffre = pdb.gimp_image_get_active_layer(imagechiffre) pdb.gimp_selection_all(imagechiffre) pdb.gimp_edit_copy(layerchiffre) pdb.gimp_image_delete(imagechiffre) floating_sel = pdb.gimp_edit_paste(layer,False) pdb.gimp_floating_sel_anchor(floating_sel)
def MDColors(image, layer, srcmode, dstmode, shlmode): lut = BuildColorLUT(srcmode, dstmode, shlmode) gimp.progress_init("Converting to MD colors...") # Indexed images are faster if layer.is_indexed: ConvertColormap(image, lut) else: pdb.gimp_image_undo_group_start(image) # Get the layer position. pos = FindLayer(image, layer) # Create a new layer to save the results (otherwise is not possible to undo the operation). newLayer = layer.copy() image.add_layer(newLayer, pos) layerName = layer.name # Clear the new layer. pdb.gimp_edit_clear(newLayer) newLayer.flush() # Calculate the number of tiles. tile_width = gimp.tile_width() tile_height = gimp.tile_height() # Ceiling division width_tiles = -(-layer.width // tile_width) height_tiles = -(-layer.height // tile_height) # Iterate over the tiles. for col in xrange(width_tiles): for row in xrange(height_tiles): # Update the progress bar. gimp.progress_update( float(col * height_tiles + row) / float(width_tiles * height_tiles)) ConvertTile(layer.get_tile(False, row, col), newLayer.get_tile(False, row, col), lut) # Update the new layer. newLayer.flush() newLayer.merge_shadow(True) newLayer.update(0, 0, layer.width, layer.height) # Remove the old layer. image.remove_layer(layer) newLayer.name = layerName # Update display and finish undo group. gimp.displays_flush() pdb.gimp_image_undo_group_end(image)
def effet_texte(inColor, inImg): layer = pdb.gimp_image_get_active_layer(inImg) pdb.gimp_context_set_sample_transparent(True) pdb.gimp_image_select_contiguous_color(inImg, CHANNEL_OP_REPLACE, layer, 1, 1) pdb.gimp_selection_invert(inImg) _, x, _, x2, y2 = pdb.gimp_selection_bounds(inImg) xmiddle = x + (x2 - x) // 2 y = y2 - 1 keep = True while keep: if y < 0: print("Error in effet_texte for img {} : y < 0 !".format(inImg)) return if (not _is_transparent(inImg, layer, xmiddle, y)) and _is_black(inImg, layer, xmiddle, y): keep = False pdb.gimp_context_set_sample_transparent(False) pdb.gimp_image_select_contiguous_color(inImg, CHANNEL_OP_REPLACE, layer, xmiddle, y) pdb.gimp_edit_clear(layer) y -= 1 _, x1, y1, x2, y2 = pdb.gimp_selection_bounds(inImg) newlayer = pdb.gimp_layer_copy(layer, True) pdb.gimp_image_select_rectangle(inImg, CHANNEL_OP_REPLACE, x1, y1, x2-x1, y2-y1) pdb.gimp_context_set_sample_transparent(True) pdb.gimp_image_select_contiguous_color(inImg, CHANNEL_OP_SUBTRACT, layer, x1, y1) pdb.gimp_edit_clear(layer) pdb.gimp_selection_invert(inImg) pdb.gimp_image_insert_layer(inImg, newlayer, None, 0) pdb.gimp_edit_clear(newlayer) pdb.script_fu_layerfx_outer_glow(inImg, newlayer, inColor, 75, 0, 0, 0, 0, 5, 0, 1) pdb.gimp_image_merge_visible_layers(inImg, CLIP_TO_IMAGE) pdb.gimp_selection_none(inImg) pdb.gimp_displays_flush()
def make_captcha(sx, sy, font_height, letter_spacing, left_margin, angle_range, fonts, answer): """Generate a captcha consisting of the letters in answer. :rtype: :class:`gimp.Image` :returns: The CAPTCHA as a gimp-python image object. """ img = gimp.Image(sx, sy, RGB_IMAGE) img.disable_undo() light_noise_layer = gimp.Layer(img, 'light noise', sx, sy, RGB_IMAGE, 100, NORMAL_MODE) img.add_layer(light_noise_layer, 0) gpdb.gimp_selection_none(img) gpdb.gimp_drawable_fill(light_noise_layer, WHITE_FILL) # plug_in_randomize_hurl at 1% 1 time is vastly superior to # scatter_rgb here, but has a bug where it creates an artifact at # the top of the image when invoked in a scripting context like # this. # # Future experiment: dial down the amount of noise generated by # scatter, then run it through levels to darken it, then # blur. This should be equivalent to hurl + blur. #gpdb.plug_in_randomize_hurl(img, light_noise_layer, 1, 1, 0, 0) gpdb.plug_in_scatter_hsv(img, light_noise_layer, 1, 25, 200, 180) gpdb.plug_in_gauss_iir(img, light_noise_layer, 1, 1, 1) gpdb.gimp_desaturate(light_noise_layer) # Next make pure black layer which we will copy repeatedly as a # place to cut out letters. blackLayer = gimp.Layer(img, 'black', sx, sy, RGB_IMAGE, 100, NORMAL_MODE) img.add_layer(blackLayer, 0) blackLayer.add_alpha() gpdb.gimp_layer_add_alpha(blackLayer) gpdb.gimp_drawable_fill(blackLayer, WHITE_FILL) gpdb.gimp_invert(blackLayer) # Loop through each letter, making it a separate black layer. right = left_margin last_substrate = None for letter in answer: font = random.choice(FONTS) substrate = blackLayer.copy() img.add_layer(substrate, 0) new_right = cookie_cutter_letter(img, substrate, right, font, letter) # look out for really narrow letters if new_right - right < 20: new_right += 5 right = new_right img.remove_layer(blackLayer) # Hide the light noise layer, then collapse all the remaining # layers (all letters) into a single layer. light_noise_layer.visible = False textLayer = gpdb.gimp_image_merge_visible_layers(img, CLIP_TO_IMAGE) light_noise_layer.visible = True # Create a layer of dark noise which will display the letters. dark_noise_layer = gimp.Layer(img, 'dark noise', sx, sy, RGB_IMAGE, 100, MULTIPLY_MODE) img.add_layer(dark_noise_layer, 1) gpdb.gimp_drawable_fill(dark_noise_layer, WHITE_FILL) gpdb.plug_in_randomize_hurl(img, dark_noise_layer, 25, 1, 0, 0) gpdb.gimp_desaturate(dark_noise_layer) # These next operations are ordered carefully. Changing the order # dramatically affects how the output looks. # Here's where we do the cutout operation. gpdb.gimp_selection_layer_alpha(textLayer) gpdb.gimp_selection_invert(img) gpdb.gimp_edit_clear(dark_noise_layer) gpdb.gimp_selection_none(img) # After the cutout, blur the dark noise layer and then darken it: gpdb.plug_in_gauss_iir(img, dark_noise_layer, 1, 1, 1) gpdb.gimp_levels(dark_noise_layer, HISTOGRAM_VALUE, 127, 255, 0.25, 0, 255) textLayer.visible = False # If you start gimp without --no-interface with an X server, this # line will let you see the image looks like at this point in the # script, layers and all. It should be fine to move this line to # any problematic part of the script for debugging. # # gimp.Display(gpdb.gimp_image_duplicate(img)) final = img.flatten() gpdb.gimp_image_clean_all(img) img.enable_undo() return img, final