def showWin(width, height): img = gimp.Image(width, height, RGB) lyr = gimp.Layer(img, 'layer1', width, height, RGB, 100, NORMAL_MODE) lyr.fill(BACKGROUND_FILL) img.add_layer(lyr) gimp.Display(img) gimp.displays_flush()
def create_base_alphabet(font, font_size, directory_base): suffix = '.xbm' for c_gen, c_prefix in ( (map(chr, xrange(ord('A'), ord('Z') + 1)), 'upper'), (map(chr, xrange(ord('a'), ord('z') + 1)), 'lower'), (map(chr, xrange(ord('0'), ord('9') + 1)), 'number'), ): for c in c_gen: prefix = '%s%c' % (c_prefix, c) filename = '%s%s' % (prefix, suffix) image = gimp.Image(1, 1, INDEXED) image.disable_undo() # necessary ? pdb.gimp_context_push() gimp.set_foreground((0.0, 0.0, 0.0)) x = y = border = 0 layer = pdb.gimp_text_fontname(image, None, x, y, c, border, True, font_size, PIXELS, font) image.resize(layer.width, layer.height, 0, 0) filepath = join(directory_base, filename) pdb.gimp_file_save(image, layer, filepath, '?') #pdb.file_xbm_save(RUN_NONINTERACTIVE, image, None, filename, filepath, '', 0, 0, 0) # find out how to properly call file_xbm_save so we can avoid this crap with open(filepath, 'r+b') as file_h: lines = file_h.readlines() file_h.seek(0) for line in lines: if '_' in line: if '_hot' not in line: file_h.write(line.replace('_', prefix + '_')) else: file_h.write(line) file_h.truncate() pdb.gimp_image_delete(image) # necessary ? pdb.gimp_context_pop()
def create_base_alphabet(font, font_size, directory_base): suffix = '.xbm' for c in string.printable: # Only need the first guard to prevent \x0b and \x0c, but meh if not ' ' <= c <= '\x7f': continue prefix = 'ascii0x%02x' % ord(c) filename = '%s%s' % (prefix, suffix) image = gimp.Image(1, 1, INDEXED) image.disable_undo() # necessary ? pdb.gimp_context_push() gimp.set_foreground((0.0, 0.0, 0.0)) x = y = border = 0 layer = pdb.gimp_text_fontname(image, None, x, y, c, border, True, font_size, PIXELS, font) if layer is None: print 'Failed to handle %r' % c else: image.resize(layer.width, layer.height, 0, 0) filepath = join(directory_base, filename) pdb.gimp_file_save(image, layer, filepath, '?') #pdb.file_xbm_save(RUN_NONINTERACTIVE, image, None, filename, filepath, '', 0, 0, 0) # find out how to properly call file_xbm_save so we can avoid this section with open(filepath, 'r+b') as file_h: lines = file_h.readlines() file_h.seek(0) for line in lines: if '_' in line: if '_hot' not in line: file_h.write(line.replace('_', prefix + '_')) else: file_h.write(line) file_h.truncate() pdb.gimp_image_delete(image) # necessary ? pdb.gimp_context_pop()
def imgarray_to_image(array, name): h, w, d = array.shape img = gimp.Image(w, h, image_base_type_map[d]) imgarray_to_layer(array, img, name) gimp.Display(img) 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
def create_formated_version(self, widget, format='gif'): """ Create a formated version of the animation to export as a giff or as a spritesheet. """ # disabling the onionskin temporaly if is activated oskin_disabled = False if self.oskin: self.on_onionskin(None) oskin_disabled = True # get normal and visibly fixed frames. normal_frames = filter(lambda x: x.fixed == False, self.frames) fixed_frames = filter(lambda x: x.fixed == True, self.frames) new_image = gimp.Image(self.image.width, self.image.height, self.image.base_type) # reverse the normal frames. normal_frames.reverse() for fl in normal_frames: # create a group to put the normal and the fixed frames. group = gimp.GroupLayer(new_image, fl.layer.name) # copy normal layer lcopy = pdb.gimp_layer_new_from_drawable(fl.layer, new_image) lcopy.visible = True new_image.add_layer(group, len(new_image.layers)) new_image.insert_layer(lcopy, group, 0) # get the background and foreground frames. up_fixed = filter( lambda x: self.frames.index(x) > self.frames.index(fl), fixed_frames) bottom_fixed = filter( lambda x: self.frames.index(x) < self.frames.index(fl), fixed_frames) # copy and insert the fixed visibility layers/frames b = 0 for ff in fixed_frames: copy = pdb.gimp_layer_new_from_drawable(ff.layer, new_image) if ff in bottom_fixed: new_image.insert_layer(copy, group, len(group.layers) - b) b += 1 elif ff in up_fixed: new_image.insert_layer(copy, group, 0) if format == 'gif': # show the formated image to export as gif. gimp.Display(new_image) elif format == 'spritesheet': simg = gimp.Image( len(new_image.layers) * self.image.width, self.image.height, self.image.base_type) cnt = 0 def novisible(x, state): # change the visibility of the gimp layers. x.visible = state # copy each frame and position it side by side. # put the layers order back to normal. n_img_layers = new_image.layers n_img_layers.reverse() for l in n_img_layers: cl = pdb.gimp_layer_new_from_drawable(l, simg) simg.add_layer(cl, 0) cl.transform_2d(0, 0, 1, 1, 0, -cnt * new_image.width, 0, 1, 0) cnt += 1 # merge the group as flat image. map(lambda x: novisible(x, False), simg.layers) cl.visible = True simg.merge_visible_layers(1) map(lambda x: novisible(x, True), simg.layers) # show the formated image to export as spritesheet. gimp.Display(simg) # return onionskin if was enabled if oskin_disabled: self.on_onionskin(None)
def create_wraps( src_image, # type: gimp.Image box_width_mm, # type: float box_height_mm, # type: float box_depth_mm, # type: float thickness_mm, # type: float flap_size_mm, # type: float inside_size_mm, # type: float crop_mark_size_mm, # type: float crop_mark_distance_mm # type: float ): # type: (...) -> None """Creates two wrap images from a template image.""" # Convert the dimensions from mm to px box_width = mm_to_px(box_width_mm) # type: int box_height = mm_to_px(box_height_mm) # type: int box_depth = mm_to_px(box_depth_mm) # type: int thickness = mm_to_px(thickness_mm) # type: int flap_size = mm_to_px(flap_size_mm) # type: int inside_size = mm_to_px(inside_size_mm) # type: int crop_mark_size = mm_to_px(crop_mark_size_mm) # type: int crop_mark_distance = mm_to_px(crop_mark_distance_mm) # type: int half_box_height = box_height // 2 # type: int half_box_height_plus_extra = \ half_box_height + thickness + inside_size # type: int # Coordinates in the source image src_xs, src_ys = template_coordinates(box_width, box_height, box_depth) # type: int, int src_image_width = src_xs[-1] - src_xs[0] # type: int src_image_height = src_ys[-1] - src_ys[0] # type: int # Coordinates in the destination images dst_xs, dst_ys = wrap_coordinates(box_width, box_height, box_depth, thickness, inside_size, flap_size, crop_mark_size, crop_mark_distance) dst_image_width = dst_xs[-1] - dst_xs[0] # type: int dst_image_height = dst_ys[-1] - dst_ys[0] # type: int # Make sure we have the right dimensions if src_image.width != src_image_width or \ src_image.height != src_image_height: gimp.message( "Template image has the wrong size. " "Expected %dpx x %dpx (%dmm x %dmm) " "but got %dpx x %dpx (%dmm x %dmm)." % (src_image_width, src_image_height, px_to_mm(src_image_width), px_to_mm(src_image_height), src_image.width, src_image.height, px_to_mm(src_image.width), px_to_mm(src_image.height))) return # Draw stuff onto both destination images in the same way def draw(dst_image, copy_and_rotate_definitions): """Copies regions from the input image to a wrap image.""" dst_layer = gimp.Layer(dst_image, "Wrap", dst_image_width, dst_image_height, gimpfu.RGB_IMAGE, 100, gimpfu.NORMAL_MODE) # type: gimp.Layer dst_layer.fill(gimpfu.WHITE_FILL) dst_image.add_layer(dst_layer, 0) # Add guides for x in dst_xs: # type: int dst_image.add_vguide(x) for y in dst_ys: # type: int dst_image.add_hguide(y) # Take the layers from the template and move and rotate them # into position for d in copy_and_rotate_definitions: pdb.gimp_progress_pulse() copy_and_rotate_rectangle( src_image, # src_image d[0], # src_x d[1], # src_y d[2], # src_width d[3], # src_height dst_layer, # dst_layer d[4], # dst_x d[5], # dst_y d[6], # dst_corner d[7]) # rotation_angle # Copy strips from the sides to create the flaps on the front # and the back pdb.gimp_progress_pulse() copy_and_rotate_rectangle(dst_image, dst_xs[1], dst_ys[4], half_box_height_plus_extra, flap_size, dst_layer, dst_xs[5], dst_ys[4], Corner.BOTTOM_RIGHT, 90) pdb.gimp_progress_pulse() copy_and_rotate_rectangle(dst_image, dst_xs[1], dst_ys[6], half_box_height_plus_extra, flap_size, dst_layer, dst_xs[5], dst_ys[7], Corner.TOP_RIGHT, 270) pdb.gimp_progress_pulse() copy_and_rotate_rectangle(dst_image, dst_xs[6], dst_ys[4], half_box_height_plus_extra, flap_size, dst_layer, dst_xs[6], dst_ys[4], Corner.BOTTOM_LEFT, 270) pdb.gimp_progress_pulse() copy_and_rotate_rectangle(dst_image, dst_xs[6], dst_ys[6], half_box_height_plus_extra, flap_size, dst_layer, dst_xs[6], dst_ys[7], Corner.TOP_LEFT, 90) # Marks for cutting and folding draw_mark(dst_image, (Direction.UP, Direction.LEFT), dst_xs[4], dst_ys[1], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.UP, ), dst_xs[5], dst_ys[1], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.UP, ), dst_xs[6], dst_ys[1], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.UP, Direction.RIGHT), dst_xs[7], dst_ys[1], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.UP, Direction.LEFT), dst_xs[1], dst_ys[4], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.UP, Direction.RIGHT), dst_xs[10], dst_ys[4], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, Direction.LEFT), dst_xs[1], dst_ys[7], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, Direction.RIGHT), dst_xs[10], dst_ys[7], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, Direction.LEFT), dst_xs[4], dst_ys[10], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, ), dst_xs[5], dst_ys[10], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, ), dst_xs[6], dst_ys[10], crop_mark_size, crop_mark_distance) draw_mark(dst_image, (Direction.DOWN, Direction.RIGHT), dst_xs[7], dst_ys[10], crop_mark_size, crop_mark_distance) pdb.gimp_selection_none(dst_image) # Define where from and where to we want to copy # Each line looks like this: # (src_x, src_y, src_width, src_height, # dst_x, dst_y, dst_corner, rotation_angle) copy_and_rotate_definitions_top = ( # Top (src_xs[1], src_ys[0], box_width, box_depth, dst_xs[5], dst_ys[4], Corner.TOP_LEFT, 0), # Left (src_xs[0], src_ys[1], box_depth, half_box_height_plus_extra, dst_xs[5], dst_ys[4], Corner.TOP_RIGHT, 90), # Front (src_xs[1], src_ys[1], box_width, half_box_height_plus_extra, dst_xs[5], dst_ys[7], Corner.TOP_LEFT, 0), # Right (src_xs[2], src_ys[1], box_depth, half_box_height_plus_extra, dst_xs[6], dst_ys[4], Corner.TOP_LEFT, 270), # Back (src_xs[3], src_ys[1], box_width, half_box_height_plus_extra, dst_xs[5], dst_ys[4], Corner.BOTTOM_LEFT, 180), ) copy_and_rotate_definitions_bottom = ( # Left (src_xs[0], src_ys[3] - half_box_height_plus_extra, box_depth, half_box_height_plus_extra, dst_xs[5], dst_ys[4], Corner.TOP_RIGHT, 270), # Front (src_xs[1], src_ys[3] - half_box_height_plus_extra, box_width, half_box_height_plus_extra, dst_xs[5], dst_ys[1], Corner.TOP_LEFT, 0), # Right (src_xs[2], src_ys[3] - half_box_height_plus_extra, box_depth, half_box_height_plus_extra, dst_xs[6], dst_ys[4], Corner.TOP_LEFT, 90 ), # Back (src_xs[3], src_ys[3] - half_box_height_plus_extra, box_width, half_box_height_plus_extra, dst_xs[5], dst_ys[10], Corner.BOTTOM_LEFT, 180), # Bottom (src_xs[1], src_ys[3], box_width, box_depth, dst_xs[5], dst_ys[4], Corner.TOP_LEFT, 0), ) with DefaultContext(): dst_image_top = gimp.Image(dst_image_width, dst_image_height, gimpfu.RGB) # type: gimp.Image with PausedUndo(dst_image_top): draw(dst_image_top, copy_and_rotate_definitions_top) gimp.Display(dst_image_top) dst_image_bottom = gimp.Image(dst_image_width, dst_image_height, gimpfu.RGB) # type: gimp.Image with PausedUndo(dst_image_bottom): draw(dst_image_bottom, copy_and_rotate_definitions_bottom) gimp.Display(dst_image_bottom) gimp.displays_flush()
def create_template( box_width_mm, # type: float box_height_mm, # type: float box_depth_mm # type: float ): # type: (...) -> None """Creates an empty template image given the box size.""" with DefaultContext(): box_width = mm_to_px(box_width_mm) # type: int box_height = mm_to_px(box_height_mm) # type: int box_depth = mm_to_px(box_depth_mm) # type: int xs, ys = template_coordinates(box_width, box_height, box_depth) image_width = xs[-1] - xs[0] # type: int image_height = ys[-1] - ys[0] # type: int # Create a template image with one transparent layer image = gimp.Image(image_width, image_height) # type: gimp.Image with PausedUndo(image): layer = gimp.Layer(image, "Template", image_width, image_height, gimpfu.RGBA_IMAGE, 100, gimpfu.NORMAL_MODE) # type: gimp.Layer image.add_layer(layer, 0) # Create guides for x in xs: # type: int image.add_vguide(x) for y in ys: # type: int image.add_hguide(y) # Fill the areas where the graphics go with white pdb.gimp_selection_none(image) pdb.gimp_progress_pulse() pdb.gimp_image_select_rectangle(image, gimpfu.CHANNEL_OP_ADD, xs[0], ys[1], image_width, ys[3] - ys[1]) pdb.gimp_progress_pulse() pdb.gimp_image_select_rectangle(image, gimpfu.CHANNEL_OP_ADD, xs[1], ys[0], xs[2] - xs[1], image_height) pdb.gimp_edit_fill(layer, gimpfu.WHITE_FILL) pdb.gimp_selection_none(image) def put_text(text, left, right, top, bottom): """Puts some text in the center of a rectangle.""" pdb.gimp_progress_pulse() text_size = DPI / 4 # type: int text_layer = pdb.gimp_text_layer_new( image, text, "sans-serif", text_size, gimpfu.PIXELS) # type: gimp.Layer image.add_layer(text_layer, 0) move_drawable_to(text_layer, Corner.CENTER, (left + right) // 2, (top + bottom) // 2) pdb.gimp_image_merge_down(image, text_layer, gimpfu.CLIP_TO_BOTTOM_LAYER) put_text("TOP", xs[1], xs[2], ys[0], ys[1]) put_text("LEFT", xs[0], xs[1], ys[1], ys[3]) put_text("FRONT", xs[1], xs[2], ys[1], ys[3]) put_text("RIGHT", xs[2], xs[3], ys[1], ys[3]) put_text("BACK", xs[3], xs[4], ys[1], ys[3]) put_text("BOTTOM", xs[1], xs[2], ys[3], ys[4]) put_text( "Box width: %dmm (%dpx)\n" "Box height: %dmm (%dpx)\n" "Box depth: %dmm (%dpx)" % (box_width_mm, box_width, box_height_mm, box_height, box_depth_mm, box_depth), xs[0], xs[1], ys[0], ys[1]) gimp.Display(image) gimp.displays_flush()