def cutter_batch_images( src_dir, src_ftype, limit, sl_thresh, sz_thresh, bg_manual, bg_color, bg_corner, bg_x, bg_y, padding, deskew, sq_crop, save_same, save_dir, save_ftype, save_dpi, jpg_qual, save_suffix ): ftype_match = { 'jpg': '\.[jJ][pP][eE]?[gG]$', 'bmp': '\.[bB][mM][pP]$', 'png': '\.[pP][mnNM][gG]$', 'tif': '\.[tT][iI][fF][fF]?$', } fn_match = re.compile(ftype_match.get(src_ftype, 'jpg')) for fn in os.listdir(src_dir): if not os.path.isfile(fn) or not fn_match.search(fn): continue pdb.gimp_progress_set_text('Processing %s...' % (fn, )) image = pdb.gimp_file_load(fn, fn) if not image: pdb.gimp_progress_set_text('Error loading %s...' % (fn, )) continue cutter_single_image( image, image.active_layer, limit, sl_thresh, sz_thresh, bg_manual, bg_color, bg_corner, bg_x, bg_y, padding, deskew, sq_crop, True, save_same, save_dir, save_ftype, save_dpi, jpg_qual, save_suffix ) pdb.gimp_delete_image(image) pdb.gimp_progress_end()
def halftone_layer(img, layer, layer_dest, density, color, circle_size, black_strength): """ halftone the layer """ gimp.progress_init("Generating " + layer_dest.name) circles_count = 0 start = timer() source_region = layer.get_pixel_rgn(0, 0, layer.width, layer.height, False, False) pixel_size = len(source_region[0, 0]) source_pixels = array("B", source_region[0:layer.width, 0:layer.height]) print(pixel_size, len(source_pixels)) region = layer_dest.get_pixel_rgn(0, 0, layer_dest.width, layer_dest.height, True, True) # pixel_size = 4 n = layer_dest.width * layer_dest.height pixels = array("B", "\xFF" * (n * pixel_size)) for i in range(0, (layer.height / density) + 1): for j in range(0, (layer.width / density) + 1): percent = ((i * layer.width + j) / float( (layer.height * layer.width))) * density gimp.progress_update(percent) x = j * density y = i * density x_2 = x + density if x + density < layer.width else layer.width y_2 = y + density if y + density < layer.height else layer.height if x_2 == x or y_2 == y: continue box = (x, y, x_2, y_2) mean_bright = get_mean_brightness(source_pixels, box, layer.width, layer.height, pixel_size) max_strength = 255 if color == (0, 0, 0, 255): # manage black strength max_strength = 510 - black_strength isz = get_value_in_range(mean_bright, 0, max_strength, 0, circle_size) if isz > 0: circles_count += 1 draw_circle_on_pixels_region(pixels, layer_dest.width, layer_dest.height, x + density / 2, y + density / 2, isz, color) # Write our changes back over the original layer region[0:layer_dest.width, 0:layer_dest.height] = pixels.tostring() layer_dest.flush() layer_dest.merge_shadow(True) layer_dest.update(0, 0, layer_dest.width, layer_dest.height) pdb.gimp_progress_end() end = timer() print(circles_count, 'in', end - start, float(end - start) / circles_count)
def cutter_single_image( image, drawable, limit, sl_thresh, sz_thresh, bg_manual, bg_color, bg_corner, bg_x, bg_y, padding, deskew, sq_crop, autoclose, save_same, save_dir, save_ftype, save_dpi, jpg_qual, save_suffix ): img_width = pdb.gimp_image_width(image) img_height = pdb.gimp_image_height(image) img_fullpath = pdb.gimp_image_get_filename(image) img_filename = os.path.basename(img_fullpath) img_name = '.'.join(img_filename.split('.')[:-1]) img_ext = save_ftype or img_filename.split('.')[-1].lower() new_filename_tpl = ''.join([ img_name, '-', save_suffix, '-', '%0', str(len(str(int(limit + 1)))), 'd', '.', img_ext ]) new_fullpath_tpl = os.path.join( os.path.dirname(img_fullpath) if save_same else save_dir, new_filename_tpl ) # gimp.message(new_fullpath_tpl) # function code goes here... gimp.context_push() pdb.gimp_image_undo_disable(image) # If the background wasn't manually defined, pick the colour from one of the four corners # (using radius 5 average) if not bg_manual: if bg_corner in (1, 3): bg_x = img_width - bg_x if bg_corner in (2, 3): bg_y = img_height - bg_y bg_color = pdb.gimp_image_pick_color(image, drawable, bg_x, bg_y, True, True, 5) pdb.gimp_context_set_defaults() pdb.gimp_context_set_antialias(True) pdb.gimp_context_set_sample_transparent(True) pdb.gimp_context_set_sample_threshold_int(sl_thresh) pdb.gimp_context_set_feather(True) fr = min(img_width, img_height) / 100.0 # NOTE why??? pdb.gimp_context_set_feather_radius(fr, fr) pdb.gimp_context_set_background(bg_color) pdb.gimp_image_select_color(image, gimpfu.CHANNEL_OP_REPLACE, drawable, bg_color) # convert inverted copy of the background selection to a path pdb.gimp_selection_sharpen(image) pdb.gimp_selection_invert(image) # _, before = pdb.gimp_image_get_vectors(image) pdb.plug_in_sel2path(image, drawable) # _, after = pdb.gimp_image_get_vectors(image) # newpath_id = list(set(after) - set(before))[0] # newpath = gimp.Vectors.from_id(newpath_id) # looks like newly created vector is always active, so this should be sufficent newpath = pdb.gimp_image_get_active_vectors(image) pdb.gimp_context_set_feather(False) _, strokes = pdb.gimp_vectors_get_strokes(newpath) extracted = 0 for stroke_id in strokes: stroke_points = pdb.gimp_vectors_stroke_get_points(newpath, stroke_id) # skip not closed paths if not stroke_points[3]: continue temp_vector = pdb.gimp_vectors_new(image, '-temp-') pdb.gimp_image_insert_vectors(image, temp_vector, None, -1) pdb.gimp_vectors_stroke_new_from_points(temp_vector, *stroke_points) pdb.gimp_image_select_item(image, gimpfu.CHANNEL_OP_REPLACE, temp_vector) pdb.gimp_image_remove_vectors(image, temp_vector) # check for minimum size bounds = pdb.gimp_selection_bounds(image) sizex = bounds[3] - bounds[1] sizey = bounds[4] - bounds[2] if (min(sizex, sizey) < sz_thresh or sizex >= img_width or sizey >= img_height): continue buffname = "dsibuff" if deskew and pdb.gimp_procedural_db_proc_exists('gimp_deskew_plugin'): pdb.gimp_progress_set_text('Running deskew plugin...') pdb.gimp_image_select_rectangle( image, gimpfu.CHANNEL_OP_REPLACE, bounds[1], bounds[2], sizex, sizey ) buffname = pdb.gimp_edit_named_copy(drawable, buffname) temp_image = pdb.gimp_edit_named_paste_as_new(buffname) temp_layer = pdb.gimp_image_get_active_layer(temp_image) pdb.gimp_image_undo_disable(temp_image) pdb.gimp_layer_flatten(temp_layer) # RUN_NONINTERACTIVE causes 'calling error' exception pdb.gimp_deskew_plugin(temp_image, temp_layer, 0, 0, 0, 0, True, run_mode=gimpfu.RUN_INTERACTIVE) pdb.gimp_image_resize_to_layers(temp_image) pdb.gimp_layer_flatten(temp_layer) pdb.gimp_image_select_contiguous_color( temp_image, gimpfu.CHANNEL_OP_REPLACE, temp_layer, 0, 0 ) pdb.gimp_selection_invert(temp_image) bounds = pdb.gimp_selection_bounds(temp_image) sizex = bounds[3] - bounds[1] sizey = bounds[4] - bounds[2] pdb.gimp_selection_none(temp_image) pdb.gimp_image_crop(temp_image, sizex, sizey, bounds[1], bounds[2]) if (sq_crop and sizex != sizey and pdb.gimp_procedural_db_proc_exists('script_fu_addborder')): if sizex > sizey: dx = 0 dy = (sizex - sizey) * 0.5 else: dx = (sizey - sizex) * 0.5 dy = 0 pdb.script_fu_addborder(temp_image, temp_layer, dx, dy, bg_color, 0) pdb.gimp_image_raise_item_to_top(temp_image, temp_layer) pdb.gimp_image_merge_visible_layers(temp_image, gimpfu.EXPAND_AS_NECESSARY) temp_layer = pdb.gimp_image_get_active_layer(temp_image) else: temp_image = image pdb.gimp_image_undo_disable(temp_image) temp_layer = pdb.gimp_image_get_active_layer(temp_image) if sq_crop: c_x = 0.5 * (bounds[1] + bounds[3]) c_y = 0.5 * (bounds[2] + bounds[4]) hl = padding + max(sizex, sizey) * 0.5 sel_x = c_x - hl sel_y = c_y - hl sel_w = sel_h = 2 * hl else: sel_x = bounds[1] sel_y = bounds[2] sel_w = sizex sel_h = sizey pdb.gimp_image_select_rectangle( temp_image, gimpfu.CHANNEL_OP_REPLACE, sel_x, sel_y, sel_w, sel_h ) buffname = pdb.gimp_edit_named_copy(drawable, buffname) temp_image = pdb.gimp_edit_named_paste_as_new(buffname) temp_layer = pdb.gimp_image_get_active_layer(temp_image) if padding and pdb.gimp_procedural_db_proc_exists('script_fu_addborder'): pdb.script_fu_addborder(temp_image, temp_layer, padding, padding, bg_color, 0) pdb.gimp_image_merge_visible_layers(temp_image, gimpfu.EXPAND_AS_NECESSARY) temp_layer = pdb.gimp_image_get_active_layer(temp_image) pdb.gimp_image_undo_enable(temp_image) temp_display = pdb.gimp_display_new(temp_image) extracted += 1 filename = new_fullpath_tpl % (extracted, ) pdb.gimp_image_set_resolution(temp_image, save_dpi, save_dpi) if img_ext == 'jpg': pdb.file_jpeg_save( temp_image, temp_layer, filename, filename, jpg_qual, 0.1, 1, 1, '', 2, 0, 0, 1 ) else: pdb.gimp_file_save(temp_image, temp_layer, filename, filename) if autoclose: pdb.gimp_display_delete(temp_display) if extracted >= limit: break pdb.gimp_progress_set_text('Extracted %d images' % (extracted, )) pdb.gimp_image_remove_vectors(image, newpath) pdb.gimp_selection_none(image) pdb.gimp_image_undo_enable(image) pdb.gimp_progress_end() pdb.gimp_displays_flush() gimp.context_pop() return extracted
def printMessage(message): pdb.gimp_progress_end() gimp.message(message)
def add_cmyk_layers(img, layer): """ decompose layer in cmyk components """ # Obtain layer dimensions. width = layer.width height = layer.height # Make sure this layer supports alpha so we can write to each pixel's alpha # component layer.add_alpha() for k in range(0, 4): # Grab a pixel region (readonly) covering the entire image and copy # pixel data into an array source_region = layer.get_pixel_rgn(0, 0, width, height, False, False) source_pixels = array("B", source_region[0:width, 0:height]) pixel_size = len(source_region[0, 0]) print("pixel_size", pixel_size) # Create component layer in the Image component_layer = pdb.gimp_layer_new(img, width, height, RGBA_IMAGE, COMPONENT_STRING[k], 100, LAYER_MODE_NORMAL) pdb.gimp_image_insert_layer(img, component_layer, None, 0) pdb.gimp_drawable_fill(component_layer, FILL_WHITE) # Create another region (writeable) and an array that can store all # our modified pixels component_region = component_layer.get_pixel_rgn( 0, 0, width, height, True, True) component_pixels = array("B", "\x00" * (width * height * pixel_size)) gimp.progress_init("getting " + COMPONENT_STRING[k] + " component layer...") x = 0 y = 0 # Loop through every pixel in the image/layer for y in xrange(0, (height - 1)): for x in xrange(0, (width - 1)): gimp.progress_update(1.0 * y / height) source_index = (x + width * y) * pixel_size pixel = source_pixels[source_index:source_index + pixel_size] # Write the modified pixel out to our destination array component_pixel = pixel # intensity = 0 if k == 3: # black specific intensity = pixel[k] # intensity = int(round(pixel[0] * 0.2126 + # pixel[1] * 0.7152 + # pixel[2] * 0.0722)) # c_linear = (pixel[0] / 255.0) * 0.2126 # + (pixel[1] / 255.0) * 0.7152 # + (pixel[2] / 255.0) * 0.0722 # intensity = 12.92 * c_linear if c_linear <= 0.0031308 else 1.055 * \ # pow(c_linear, 1/2.4) - 0.055 # intensity = int(round(intensity*255.0)) intensity = int( round(pixel[0] * 0.299 + pixel[1] * 0.587 + pixel[2] * 0.114)) else: intensity = pixel[k] component_pixel[3] = (255 - intensity) component_pixel[0] = COLORS[k][0] component_pixel[1] = COLORS[k][1] component_pixel[2] = COLORS[k][2] component_pixels[source_index:source_index + pixel_size] = component_pixel # Copy the whole array into the writeable pixel region component_region[0:width, 0:height] = component_pixels.tostring() # Write our changes back over the original layer component_layer.flush() component_layer.merge_shadow(True) component_layer.update(0, 0, width, height) pdb.gimp_progress_end() pdb.gimp_displays_flush()