6 Create new image having texture synthesized from the selection.
7 Works best if selection is natural (fractal).
8 Can work with man-made regular texture.
9 Works worst with man-made, structured but not regular, symbols.
10 Sometimes called rendering a texture.
12 Requires resynthesizer plug-in.
15 lloyd konneker, lkk, bootch at nc.rr.com
18 1.0 lkk 7/15/2010 Initial version
19 1.1 lkk 4/10/2011 Fixed a bug with layer types impacting greyscale images.
23 This program is free software; you can redistribute it and/or modify
24 it under the terms of the GNU General Public License as published by
25 the Free Software Foundation; either version 2 of the License, or
26 (at your option) any later version.
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 The GNU Public License is available at
34 http://www.gnu.org/copyleft/gpl.html
38 Similar to "Fill resynthesized pattern" except:
39 - here the arguments are reversed: you select a texture and create a new image
40 instead of selecting an area and choosing a pattern.
41 - here the result is less random (since Fill resynthesized adds noise.)
42 Different from tiling since:
43 - seamless and irregular pattern
45 The continuum of randomness versus speed:
46 - Filters.Map.Tile is fast but has seams and regular pattern (even if you use "Make Seamless" first.)
47 - Filter.Render.Texture a tile followed by tiling is seamless but still has regularity.
48 - Filte.Render.Texture an entire image is slower but seamless and moderately irregular.
49 - Edit.Fill with resynthesized pattern is slowest but seamless and highly irregular, unpatterned.
51 This filter is not tiling (instead resynthesizing) but makes
52 an image that you can then use to tile with especially if
53 you choose the option to make the edges suitable for tiling.
55 IN: The selection (or the entire active drawable) is the source of texture and is not changed.
56 OUT New image, possibly resized canvas, same scale and resolution.
58 TODO a quality setting
63 gettext.install("resynthesizer", gimp.locale_directory, unicode=True)
68 def new_resized_image(image, resize_ratio):
69 # Create new image resized by a ratio from *selection* in the old image
71 (is_selection, ulx, uly, lrx, lry) = pdb.gimp_selection_bounds(image)
73 # Resynthesizer will use the entire source image as corpus.
74 # Resize new image in proportion to entire source image.
75 new_width = int(pdb.gimp_image_width(image) * resize_ratio)
76 new_height = int(pdb.gimp_image_height(image) * resize_ratio)
77 new_type = pdb.gimp_image_base_type(image) # same as source
79 # Resize new image in proportion to selection in source
80 new_width = int((lrx - ulx) * resize_ratio)
81 new_height = int((lry - uly) * resize_ratio)
83 new_basetype = pdb.gimp_image_base_type(image) # same as source
84 new_layertype = pdb.gimp_drawable_type(pdb.gimp_image_get_active_layer(image))
85 new_image = pdb.gimp_image_new(new_width, new_height, new_basetype)
86 # !!! Note that gimp_layer_new wants a layer type, not an image basetype
87 new_drawable = pdb.gimp_layer_new(new_image, new_width, new_height,
88 new_layertype, "Texture", 100, NORMAL_MODE)
89 pdb.gimp_image_add_layer(new_image, new_drawable, 0)
90 return new_image, new_drawable
93 def display_image(image):
97 pass # If runmode is NONINTERACTIVE, expect gimp_display_new() to fail
101 def render_texture(image, drawable, resize_ratio=2, make_tile=0):
103 Create a randomized texture image from the selection.
104 The image can be suited for further, seamless tiling.
105 The image is same scale and resolution but resized from the selection.
106 Not undoable, no changes to the source (you can just delete the new image.)
108 A selection in the source image is optional.
109 If there is no selection, the resynthesizer will use the entire source image.
112 # Its all or nothing, user must delete new image if not happy.
113 pdb.gimp_image_undo_disable(image)
116 Create new image, optionally resized, and display for it.
118 new_image, new_drawable = new_resized_image(image, resize_ratio)
119 pdb.gimp_image_undo_disable(new_image)
121 raise RuntimeError, "Failed create layer."
123 # If using new resynthesizer with animation for debugging
125 display_image(new_image)
128 copy original into temp and crop it to the selection to save memory in resynthesizer
130 temp_image = pdb.gimp_image_duplicate(image)
132 raise RuntimeError, "Failed duplicate image"
134 # Get bounds, offset of selection
135 (is_selection, ulx, uly, lrx, lry) = pdb.gimp_selection_bounds(image)
136 if not is_selection :
137 # No need to crop. Resynthesizer will use all if no selection.
140 pdb.gimp_image_crop(temp_image, lrx - ulx, lry - uly, ulx, uly)
142 # Don't flatten because it turns transparency to background (white usually)
143 work_layer = pdb.gimp_image_get_active_layer(temp_image)
145 raise RuntimeError, "Failed get active layer"
147 # Insure the selection is all (not necessary, resynthesizer will use all if no selection.)
148 pdb.gimp_selection_all(temp_image)
150 # Settings for making edges suitable for seamless tiling afterwards.
151 # That is what these settings mean in the resynthesizer:
152 # wrap context probes in the target so that edges of target will be suitable for seamless tiling.
153 # I.E. treat the target as a sphere when matching.
162 # use_border is moot since there is no context (outside the target) in the newImage.
163 # The target is the entire new image, the source is the cropped copy of the selection.
165 # 9 neighbors (a 3x3 patch) and 200 tries for speed, since new image is probably large
166 # and source is probably natural (fractal), where quality is not important.
168 # For version of resynthesizer with uninverted selection
169 # !!! Pass -1 for ID of no layer, not None
170 pdb.plug_in_resynthesizer(new_image, new_drawable, htile, vtile, 0, work_layer.ID, -1, -1, 0.0, 0.117, 9, 200)
172 display_image(new_image)
175 pdb.gimp_image_delete(temp_image)
176 pdb.gimp_image_undo_enable(image)
177 pdb.gimp_image_undo_enable(new_image)
182 "python_fu_render_texture",
183 N_("Create a new image with texture from the current image or selection. Optionally, create image edges suited for further, seamless tiling. "),
184 "New image is the same scale but seamless and irregular. Use 'Map>Tile' for less randomness. Use 'Edit>Fill resynthesized pattern' for more randomness. Requires separate resynthesizer plugin.",
186 "Copyright 2010 Lloyd Konneker",
191 (PF_IMAGE, "image", "Input image", None),
192 (PF_DRAWABLE, "drawable", "Input drawable", None),
193 # Spinner is digital and linear, slider is analog but exponential
194 (PF_SPINNER, "resize_ratio", _("Ratio of size of new image to source selection"), 2, (0.5, 10, 0.5)),
195 (PF_TOGGLE, "make_tile", _("Make new image edges suitable for seamless tiling"), 0 )
197 [(PF_IMAGE, "new_image", "New, synthesized texture.")],
199 menu="<Image>/Filters/Render",
200 domain=("resynthesizer", gimp.locale_directory)