gimp-mcp-plugin 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gimp_mcp_docs/best_practices.md +290 -0
- gimp_mcp_docs/iterative_workflow.md +311 -0
- gimp_mcp_plugin-0.1.0.dist-info/METADATA +539 -0
- gimp_mcp_plugin-0.1.0.dist-info/RECORD +9 -0
- gimp_mcp_plugin-0.1.0.dist-info/WHEEL +5 -0
- gimp_mcp_plugin-0.1.0.dist-info/entry_points.txt +3 -0
- gimp_mcp_plugin-0.1.0.dist-info/licenses/LICENSE +674 -0
- gimp_mcp_plugin-0.1.0.dist-info/top_level.txt +2 -0
- gimp_mcp_server.py +2859 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# GIMP MCP Best Practices & Recipes
|
|
2
|
+
|
|
3
|
+
## ✅ FILLING SHAPES - The Right Way
|
|
4
|
+
|
|
5
|
+
**DO: Use Polygon Selection for Filled Shapes**
|
|
6
|
+
```python
|
|
7
|
+
# Best method for solid filled shapes
|
|
8
|
+
points = [x1, y1, x2, y2, x3, y3, ...] # Flat array of coordinates
|
|
9
|
+
Gimp.Image.select_polygon(image, Gimp.ChannelOps.REPLACE, points)
|
|
10
|
+
Gimp.context_set_foreground(color)
|
|
11
|
+
Gimp.Drawable.edit_fill(drawable, Gimp.FillType.FOREGROUND)
|
|
12
|
+
Gimp.Selection.none(image)
|
|
13
|
+
Gimp.displays_flush()
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**DON'T: Use Paintbrush for Filling Areas**
|
|
17
|
+
```python
|
|
18
|
+
# ❌ This creates thin strokes, not solid fills
|
|
19
|
+
points = [x1, y1, x2, y2, x3, y3, ...]
|
|
20
|
+
Gimp.paintbrush_default(drawable, points) # Creates outline only!
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**WHY**: The paintbrush tool draws along a path with the current brush size. For solid fills, polygon selection ensures complete coverage.
|
|
24
|
+
|
|
25
|
+
## ✅ BEZIER PATHS - For Outlines Only
|
|
26
|
+
|
|
27
|
+
**DO: Use Bezier Paths for Smooth Outlines**
|
|
28
|
+
```python
|
|
29
|
+
# Bezier paths are perfect for stroked outlines with curves
|
|
30
|
+
path = Gimp.Path.new(image, 'curved_outline')
|
|
31
|
+
image.insert_path(path, None, 0)
|
|
32
|
+
stroke_id = path.bezier_stroke_new_moveto(x1, y1)
|
|
33
|
+
path.bezier_stroke_cubicto(stroke_id, cx1, cy1, cx2, cy2, x2, y2)
|
|
34
|
+
# Stroke creates the outline
|
|
35
|
+
Gimp.Drawable.edit_stroke_item(drawable, path)
|
|
36
|
+
Gimp.displays_flush()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**DON'T: Try to Fill Bezier Paths Directly**
|
|
40
|
+
```python
|
|
41
|
+
# ❌ This method doesn't exist in GIMP 3.0
|
|
42
|
+
path.to_selection() # AttributeError!
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**WHY**: GIMP 3.0's bezier paths are designed for vector strokes. For filled curved shapes, approximate with polygon selections or use multiple overlapping ellipses.
|
|
46
|
+
|
|
47
|
+
## ✅ VARIABLE PERSISTENCE - Reuse, Don't Repeat
|
|
48
|
+
|
|
49
|
+
**DO: Initialize Once, Reuse**
|
|
50
|
+
```python
|
|
51
|
+
# First call - set up context
|
|
52
|
+
["from gi.repository import Gimp, Gegl",
|
|
53
|
+
"images = Gimp.get_images()",
|
|
54
|
+
"image1 = images[0]",
|
|
55
|
+
"layer1 = image1.get_layers()[0]",
|
|
56
|
+
"drawable1 = layer1"]
|
|
57
|
+
|
|
58
|
+
# Later calls - variables still available
|
|
59
|
+
["Gimp.Selection.all(image1)",
|
|
60
|
+
"Gimp.Drawable.edit_fill(drawable1, Gimp.FillType.FOREGROUND)"]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**DON'T: Repeat Imports and Initialization**
|
|
64
|
+
```python
|
|
65
|
+
# ❌ Wasteful - these persist between calls
|
|
66
|
+
["from gi.repository import Gimp", # Already imported!
|
|
67
|
+
"images = Gimp.get_images()", # Already have this!
|
|
68
|
+
"image1 = images[0]"] # Already assigned!
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**WHY**: PyGObject console maintains a persistent Python environment. Variables, imports, and functions remain in memory between calls.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## ✅ SELECTION FEATHERING - Use Sparingly
|
|
76
|
+
|
|
77
|
+
**DO: Use Sharp Selections by Default**
|
|
78
|
+
```python
|
|
79
|
+
# Most shapes should have clean, sharp edges
|
|
80
|
+
points = [x1, y1, x2, y2, x3, y3, ...]
|
|
81
|
+
Gimp.Image.select_polygon(image, Gimp.ChannelOps.REPLACE, points)
|
|
82
|
+
# NO feathering - fills will have sharp, clean edges
|
|
83
|
+
Gimp.Drawable.edit_fill(drawable, Gimp.FillType.FOREGROUND)
|
|
84
|
+
Gimp.Selection.none(image)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**DON'T: Add Feathering Without Good Reason**
|
|
88
|
+
```python
|
|
89
|
+
# ❌ This creates blurry, unclear edges
|
|
90
|
+
Gimp.Image.select_ellipse(image, Gimp.ChannelOps.REPLACE, x, y, w, h)
|
|
91
|
+
Gimp.Selection.feather(image, 10) # Blurs the edges!
|
|
92
|
+
Gimp.Drawable.edit_fill(drawable, Gimp.FillType.FOREGROUND)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**WHEN to Use Feathering:**
|
|
96
|
+
- Soft shadows or glows
|
|
97
|
+
- Blending elements naturally into backgrounds
|
|
98
|
+
- Creating soft, artistic effects
|
|
99
|
+
- ONLY when explicitly requested by user
|
|
100
|
+
|
|
101
|
+
**WHY**: Sharp edges look professional and clean. Feathering creates blurry, unclear edges that make drawings look unprofessional unless specifically needed for artistic effect.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Common Recipes
|
|
106
|
+
|
|
107
|
+
### Initialization
|
|
108
|
+
```python
|
|
109
|
+
# Basic initialization
|
|
110
|
+
["from gi.repository import Gimp, Gegl"]
|
|
111
|
+
|
|
112
|
+
# Recommended full initialization
|
|
113
|
+
["from gi.repository import Gimp, Gegl",
|
|
114
|
+
"images = Gimp.get_images()",
|
|
115
|
+
"image1 = images[0]",
|
|
116
|
+
"layer1 = image1.get_layers()[0]",
|
|
117
|
+
"drawable1 = layer1"]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Setting Colors
|
|
121
|
+
```python
|
|
122
|
+
# Set foreground to red
|
|
123
|
+
["red_color = Gegl.Color.new('red')",
|
|
124
|
+
"Gimp.context_set_foreground(red_color)"]
|
|
125
|
+
|
|
126
|
+
# Set foreground to black
|
|
127
|
+
["black_color = Gegl.Color.new('black')",
|
|
128
|
+
"Gimp.context_set_foreground(black_color)"]
|
|
129
|
+
|
|
130
|
+
# Set background to white
|
|
131
|
+
["white_color = Gegl.Color.new('white')",
|
|
132
|
+
"Gimp.context_set_background(white_color)"]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Drawing Operations
|
|
136
|
+
|
|
137
|
+
**Draw a Line**
|
|
138
|
+
```python
|
|
139
|
+
["Gimp.pencil(drawable1, [0, 0, 200, 200])",
|
|
140
|
+
"Gimp.displays_flush()"]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Draw a Filled Ellipse**
|
|
144
|
+
```python
|
|
145
|
+
["Gimp.Image.select_ellipse(image1, Gimp.ChannelOps.REPLACE, 100, 100, 30, 20)",
|
|
146
|
+
"Gimp.Drawable.edit_fill(drawable1, Gimp.FillType.FOREGROUND)",
|
|
147
|
+
"Gimp.Selection.none(image1)",
|
|
148
|
+
"Gimp.displays_flush()"]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Paint a Curve with Brush (for strokes, not fills)**
|
|
152
|
+
```python
|
|
153
|
+
# Note: Use this for decorative strokes or outlines, NOT for filling shapes
|
|
154
|
+
["Gimp.paintbrush_default(drawable1, [50.0, 50.0, 150.0, 200.0, 250.0, 50.0, 350.0, 200.0])",
|
|
155
|
+
"Gimp.displays_flush()"]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Draw a Bezier Curve (for outlines)**
|
|
159
|
+
```python
|
|
160
|
+
["path = Gimp.Path.new(image1, 'my_bezier_path')",
|
|
161
|
+
"image1.insert_path(path, None, 0)",
|
|
162
|
+
"stroke_id = path.bezier_stroke_new_moveto(100, 100)",
|
|
163
|
+
"path.bezier_stroke_cubicto(stroke_id, 150, 50, 250, 150, 300, 100)",
|
|
164
|
+
"Gimp.Drawable.edit_stroke_item(drawable1, path)",
|
|
165
|
+
"Gimp.Selection.none(image1)",
|
|
166
|
+
"Gimp.displays_flush()"]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Image Management
|
|
170
|
+
|
|
171
|
+
**Create a New Image**
|
|
172
|
+
```python
|
|
173
|
+
["from gi.repository import Gimp, Gegl",
|
|
174
|
+
"image1 = Gimp.Image.new(350, 800, Gimp.ImageBaseType.RGB)",
|
|
175
|
+
"layer1 = Gimp.Layer.new(image1, 'Background', 350, 800, Gimp.ImageType.RGB_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
176
|
+
"image1.insert_layer(layer1, None, 0)",
|
|
177
|
+
"drawable1 = layer1",
|
|
178
|
+
"white_color = Gegl.Color.new('white')",
|
|
179
|
+
"Gimp.context_set_background(white_color)",
|
|
180
|
+
"Gimp.Drawable.edit_fill(drawable1, Gimp.FillType.BACKGROUND)",
|
|
181
|
+
"Gimp.Display.new(image1)"]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Get Open Filenames**
|
|
185
|
+
```python
|
|
186
|
+
["print([x.get_file().get_path() for x in Gimp.get_images()])"]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Copy Layer Between Images**
|
|
190
|
+
```python
|
|
191
|
+
["image1 = Gimp.get_images()[0]",
|
|
192
|
+
"image2 = Gimp.get_images()[1]",
|
|
193
|
+
"width = image1.get_width()",
|
|
194
|
+
"height = image1.get_height()",
|
|
195
|
+
"image1.select_rectangle(Gimp.ChannelOps.REPLACE, 0, 0, width, height)",
|
|
196
|
+
"image1_layers = image1.get_selected_layers()",
|
|
197
|
+
"drawable = image1_layers[0]",
|
|
198
|
+
"Gimp.edit_copy([drawable])",
|
|
199
|
+
"image2_layers = image2.get_layers()",
|
|
200
|
+
"target_drawable = image2_layers[0]",
|
|
201
|
+
"floating_sel = Gimp.edit_paste(target_drawable, True)[0]",
|
|
202
|
+
"Gimp.floating_sel_anchor(floating_sel)",
|
|
203
|
+
"Gimp.displays_flush()"]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Tips & Guidelines
|
|
209
|
+
|
|
210
|
+
### Verification After Drawing
|
|
211
|
+
After drawing operations, capture a high-resolution region to verify output quality:
|
|
212
|
+
- Use `get_image_bitmap()` with region parameter to check specific areas
|
|
213
|
+
- Extract only the modified area (saves resources, faster feedback)
|
|
214
|
+
- Can use higher resolution for small regions
|
|
215
|
+
- Example: After drawing a face, get just the face region at high quality
|
|
216
|
+
- Catch issues early before continuing to next elements
|
|
217
|
+
|
|
218
|
+
### Context State Awareness
|
|
219
|
+
Check `get_context_state()` before operations that depend on settings:
|
|
220
|
+
- User can change colors, brush, or settings in GIMP UI at any time
|
|
221
|
+
- Verify foreground/background colors before drawing
|
|
222
|
+
- Check if feathering is enabled (to avoid unwanted blurry edges)
|
|
223
|
+
- Ensure opacity and blend mode are as expected
|
|
224
|
+
- Example: Before drawing red circle, verify foreground is actually red
|
|
225
|
+
|
|
226
|
+
### API Verification
|
|
227
|
+
- Before executing any API command you haven't verified, consult the documentation at https://developer.gimp.org/api/3.0/libgimp/
|
|
228
|
+
- After executing a command, verify GIMP responded with a successful message, e.g., `{"status": "success", "results": ["", "", ...]}`
|
|
229
|
+
|
|
230
|
+
### Display Updates
|
|
231
|
+
- After drawing operations, always call `Gimp.displays_flush()`
|
|
232
|
+
- After selection operations for drawing, unselect with `Gimp.Selection.none(image)`
|
|
233
|
+
|
|
234
|
+
### Layer Management
|
|
235
|
+
- When filling layers with color, ensure the layer has an alpha channel using `Gimp.Layer.add_alpha()`
|
|
236
|
+
- Use `Gimp.Drawable.fill()` for reliable full-layer fills
|
|
237
|
+
- Specify colors precisely with `rgb(R, G, B)` or `rgba(R, G, B, A)` to avoid transparency issues
|
|
238
|
+
|
|
239
|
+
### Context Efficiency
|
|
240
|
+
- No need to repeat import commands - once imported, packages remain available
|
|
241
|
+
- Variables persist between calls - initialize once, reuse many times
|
|
242
|
+
- Use `Gimp.context_push()` and `Gimp.context_pop()` to save/restore context when needed
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## ✅ SELF-CRITIQUE CHECKLIST
|
|
247
|
+
|
|
248
|
+
After calling `get_image_bitmap()`, systematically check:
|
|
249
|
+
|
|
250
|
+
### Visual Inspection
|
|
251
|
+
- [ ] Do all shapes match their intended form?
|
|
252
|
+
- [ ] Are edges sharp and clean (not blurry)?
|
|
253
|
+
- [ ] Are colors correct and consistent?
|
|
254
|
+
- [ ] Are there any unwanted overlaps or artifacts?
|
|
255
|
+
- [ ] Is the overall composition balanced?
|
|
256
|
+
|
|
257
|
+
### Technical Inspection
|
|
258
|
+
- [ ] Are elements on correct layers?
|
|
259
|
+
- [ ] Were all selections cleared after use?
|
|
260
|
+
- [ ] Is Gimp.displays_flush() called after drawing?
|
|
261
|
+
- [ ] Are feather/antialiasing settings appropriate?
|
|
262
|
+
|
|
263
|
+
### Common Artifacts to Look For
|
|
264
|
+
- **Blurry/cloudy edges**: Usually from unwanted feathering - remove feathering for clean edges
|
|
265
|
+
- **Cloudy areas**: From feathered selections overlapping - avoid feathering unless explicitly needed
|
|
266
|
+
- **Missing elements**: Drew on wrong layer or forgot flush
|
|
267
|
+
- **Unexpected colors**: Forgot to set foreground/background color
|
|
268
|
+
- **Rectangular artifacts**: Forgot to clear selection
|
|
269
|
+
|
|
270
|
+
### Action Based on Inspection
|
|
271
|
+
|
|
272
|
+
**If everything looks good:**
|
|
273
|
+
- Proceed to next phase
|
|
274
|
+
- Document what works for future reference
|
|
275
|
+
|
|
276
|
+
**If issues found:**
|
|
277
|
+
- STOP drawing new elements
|
|
278
|
+
- Identify which layer has the problem
|
|
279
|
+
- Fix on that specific layer
|
|
280
|
+
- Validate fix with another get_image_bitmap()
|
|
281
|
+
- Only continue when satisfied
|
|
282
|
+
|
|
283
|
+
**Never:**
|
|
284
|
+
- Paint over problems (creates more problems)
|
|
285
|
+
- Continue when something looks wrong
|
|
286
|
+
- Skip validation "to save time"
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
These patterns are based on practical experience and will help you succeed faster with GIMP MCP operations.
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# Iterative Workflow with GIMP MCP
|
|
2
|
+
|
|
3
|
+
## The Golden Rule
|
|
4
|
+
|
|
5
|
+
**Check your work after every 3-5 operations. Don't continue blindly.**
|
|
6
|
+
|
|
7
|
+
## Why Iterative Workflow Matters
|
|
8
|
+
|
|
9
|
+
### Common Problems Without Validation
|
|
10
|
+
- AI treats GIMP like a single-canvas drawing tool
|
|
11
|
+
- Paints everything on one layer, creating overlapping messes
|
|
12
|
+
- Doesn't check work until explicitly asked
|
|
13
|
+
- Fixes problems by painting over them, creating more problems
|
|
14
|
+
- Doesn't leverage GIMP's powerful features (layers, masks, selections)
|
|
15
|
+
|
|
16
|
+
### The Better Approach
|
|
17
|
+
- Use layers to separate elements (background, body, head, details)
|
|
18
|
+
- Check work after each major step
|
|
19
|
+
- Use proper selection tools and masks
|
|
20
|
+
- Build incrementally with validation
|
|
21
|
+
- Fix issues properly by working on the right layer
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Phase-Based Workflow
|
|
26
|
+
|
|
27
|
+
### Phase 1: Planning (BEFORE drawing anything)
|
|
28
|
+
```python
|
|
29
|
+
# 1. Understand what you're working with
|
|
30
|
+
metadata = get_image_metadata()
|
|
31
|
+
print(f"Canvas: {metadata['basic']['width']}x{metadata['basic']['height']}")
|
|
32
|
+
print(f"Existing layers: {len(metadata['structure']['layers'])}")
|
|
33
|
+
|
|
34
|
+
# 2. Plan your layer structure
|
|
35
|
+
# Example for drawing an animal:
|
|
36
|
+
# - background_layer: sky and ground
|
|
37
|
+
# - body_layer: main body and legs
|
|
38
|
+
# - head_layer: head and ears
|
|
39
|
+
# - details_layer: eyes, nose, facial features
|
|
40
|
+
# - texture_layer: fur/wool texture overlay
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Phase 2: Layer Setup
|
|
44
|
+
```python
|
|
45
|
+
# Create layers BEFORE drawing
|
|
46
|
+
["from gi.repository import Gimp",
|
|
47
|
+
"images = Gimp.get_images()",
|
|
48
|
+
"image = images[0]",
|
|
49
|
+
"width = image.get_width()",
|
|
50
|
+
"height = image.get_height()",
|
|
51
|
+
|
|
52
|
+
# Create layers from back to front
|
|
53
|
+
"body_layer = Gimp.Layer.new(image, 'Body', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
54
|
+
"image.insert_layer(body_layer, None, 0)",
|
|
55
|
+
|
|
56
|
+
"head_layer = Gimp.Layer.new(image, 'Head', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
57
|
+
"image.insert_layer(head_layer, None, 0)",
|
|
58
|
+
|
|
59
|
+
"details_layer = Gimp.Layer.new(image, 'Details', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
60
|
+
"image.insert_layer(details_layer, None, 0)"]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Phase 3: Incremental Drawing with Validation
|
|
64
|
+
|
|
65
|
+
**Pattern:**
|
|
66
|
+
1. Set active layer
|
|
67
|
+
2. Draw 3-5 elements
|
|
68
|
+
3. Validate with get_image_bitmap()
|
|
69
|
+
4. Review and fix issues
|
|
70
|
+
5. Repeat
|
|
71
|
+
|
|
72
|
+
**Example:**
|
|
73
|
+
```python
|
|
74
|
+
# Step 1: Draw body on body layer
|
|
75
|
+
call_api("exec", ["pyGObject-console", [
|
|
76
|
+
"drawable = body_layer",
|
|
77
|
+
# Draw body operations...
|
|
78
|
+
"Gimp.displays_flush()"
|
|
79
|
+
]])
|
|
80
|
+
|
|
81
|
+
# Step 2: VALIDATE (critical!)
|
|
82
|
+
bitmap = get_image_bitmap(max_width=1024, max_height=1024)
|
|
83
|
+
# STOP and analyze the bitmap image you just received:
|
|
84
|
+
# 1. Describe what you see in the image
|
|
85
|
+
# 2. Compare to what you intended to draw
|
|
86
|
+
# 3. Identify specific problems (blurry edges? wrong colors? missing elements?)
|
|
87
|
+
# 4. Decide: continue or fix?
|
|
88
|
+
|
|
89
|
+
# Step 3: Fix issues if any (on correct layer!)
|
|
90
|
+
if issues_found:
|
|
91
|
+
call_api("exec", ["pyGObject-console", [
|
|
92
|
+
"drawable = body_layer", # Work on right layer
|
|
93
|
+
# Fix operations...
|
|
94
|
+
"Gimp.displays_flush()"
|
|
95
|
+
]])
|
|
96
|
+
|
|
97
|
+
# Step 4: Move to next layer
|
|
98
|
+
call_api("exec", ["pyGObject-console", [
|
|
99
|
+
"drawable = head_layer",
|
|
100
|
+
# Draw head operations...
|
|
101
|
+
"Gimp.displays_flush()"
|
|
102
|
+
]])
|
|
103
|
+
|
|
104
|
+
# Step 5: VALIDATE again
|
|
105
|
+
bitmap = get_image_bitmap(max_width=1024, max_height=1024)
|
|
106
|
+
# STOP and analyze: Does the head look correct? Any issues to fix?
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Common Mistakes to Avoid
|
|
112
|
+
|
|
113
|
+
### ❌ Mistake 1: Painting Over Problems
|
|
114
|
+
```python
|
|
115
|
+
# WRONG: Nose got covered, so paint over everything
|
|
116
|
+
["Gimp.context_set_foreground(face_color)",
|
|
117
|
+
"# Paint large area to cover the problem",
|
|
118
|
+
"# This creates more mess!"]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### ✅ Correct: Fix on Right Layer
|
|
122
|
+
```python
|
|
123
|
+
# RIGHT: Fix the specific issue
|
|
124
|
+
["# Switch to layer that has the problem",
|
|
125
|
+
"drawable = head_layer",
|
|
126
|
+
"# Clear the area properly with selection or edit_clear",
|
|
127
|
+
"# Redraw just what's needed",
|
|
128
|
+
"Gimp.displays_flush()"]
|
|
129
|
+
|
|
130
|
+
# Then validate
|
|
131
|
+
get_image_bitmap(max_width=1024, max_height=1024)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### ❌ Mistake 2: No Validation Until End
|
|
135
|
+
```python
|
|
136
|
+
# WRONG: Draw 50 operations then check
|
|
137
|
+
draw_background()
|
|
138
|
+
draw_body()
|
|
139
|
+
draw_head()
|
|
140
|
+
draw_details()
|
|
141
|
+
draw_texture()
|
|
142
|
+
# Now check... oh no, something went wrong at step 2!
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### ✅ Correct: Continuous Validation
|
|
146
|
+
```python
|
|
147
|
+
# RIGHT: Validate frequently
|
|
148
|
+
draw_background()
|
|
149
|
+
validate() # ← Check here
|
|
150
|
+
|
|
151
|
+
draw_body()
|
|
152
|
+
validate() # ← And here
|
|
153
|
+
|
|
154
|
+
draw_head()
|
|
155
|
+
validate() # ← And here
|
|
156
|
+
# Much easier to fix problems early!
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Self-Critique Questions
|
|
162
|
+
|
|
163
|
+
After each validation with `get_image_bitmap()`, ask yourself:
|
|
164
|
+
|
|
165
|
+
### 1. Layer Issues
|
|
166
|
+
- Are elements on the correct layer?
|
|
167
|
+
- Are layers overlapping correctly?
|
|
168
|
+
- Do I need to reorder layers?
|
|
169
|
+
|
|
170
|
+
### 2. Visual Quality
|
|
171
|
+
- Do shapes look like I intended?
|
|
172
|
+
- Are edges sharp and clean (not blurry)?
|
|
173
|
+
- Are colors correct? (Use get_context_state() to verify)
|
|
174
|
+
- Are there unwanted artifacts or overlaps?
|
|
175
|
+
- Did I avoid unnecessary feathering? (Check get_context_state())
|
|
176
|
+
|
|
177
|
+
### 2a. Regional Verification (Efficient)
|
|
178
|
+
- Instead of checking full image, extract just the modified region
|
|
179
|
+
- Higher resolution possible for small areas
|
|
180
|
+
- Faster feedback, saves resources
|
|
181
|
+
- Example: get_image_bitmap(region={"origin_x": 100, "origin_y": 50, "width": 200, "height": 200})
|
|
182
|
+
|
|
183
|
+
### 3. Selection Cleanup
|
|
184
|
+
- Did I clear selections after drawing?
|
|
185
|
+
- Are there selection artifacts visible?
|
|
186
|
+
|
|
187
|
+
### 4. Next Steps
|
|
188
|
+
- Is it safe to continue, or should I fix this first?
|
|
189
|
+
- What's the next logical element to draw?
|
|
190
|
+
- Which layer should it go on?
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Advanced: Layer Management
|
|
195
|
+
|
|
196
|
+
### Create Multiple Layers
|
|
197
|
+
```python
|
|
198
|
+
# Create organized layer structure
|
|
199
|
+
["from gi.repository import Gimp",
|
|
200
|
+
"image = Gimp.get_images()[0]",
|
|
201
|
+
"width, height = image.get_width(), image.get_height()",
|
|
202
|
+
|
|
203
|
+
# Background layer
|
|
204
|
+
"bg_layer = Gimp.Layer.new(image, 'Background', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
205
|
+
"image.insert_layer(bg_layer, None, 0)",
|
|
206
|
+
|
|
207
|
+
# Object layer
|
|
208
|
+
"obj_layer = Gimp.Layer.new(image, 'Object', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
209
|
+
"image.insert_layer(obj_layer, None, 0)",
|
|
210
|
+
|
|
211
|
+
# Details layer on top
|
|
212
|
+
"detail_layer = Gimp.Layer.new(image, 'Details', width, height, Gimp.ImageType.RGBA_IMAGE, 100, Gimp.LayerMode.NORMAL)",
|
|
213
|
+
"image.insert_layer(detail_layer, None, 0)"]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Switch Between Layers
|
|
217
|
+
```python
|
|
218
|
+
# Work on different layers
|
|
219
|
+
["# Get all layers",
|
|
220
|
+
"layers = image.get_layers()",
|
|
221
|
+
|
|
222
|
+
"# Work on background (bottom layer)",
|
|
223
|
+
"bg_drawable = layers[2]", # Layers are 0=top, higher indices=lower
|
|
224
|
+
"# ... draw on background ...",
|
|
225
|
+
|
|
226
|
+
"# Switch to top layer for details",
|
|
227
|
+
"detail_drawable = layers[0]",
|
|
228
|
+
"# ... draw details ...",
|
|
229
|
+
"Gimp.displays_flush()"]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Layer Visibility and Opacity
|
|
233
|
+
```python
|
|
234
|
+
# Control layer visibility and blending
|
|
235
|
+
["layer = image.get_layers()[0]",
|
|
236
|
+
|
|
237
|
+
"# Hide/show layer",
|
|
238
|
+
"layer.set_visible(False)", # Hide
|
|
239
|
+
"layer.set_visible(True)", # Show
|
|
240
|
+
|
|
241
|
+
"# Adjust opacity (0-100)",
|
|
242
|
+
"layer.set_opacity(50.0)", # 50% transparent
|
|
243
|
+
|
|
244
|
+
"Gimp.displays_flush()"]
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Fix Mistakes on Specific Layer
|
|
248
|
+
```python
|
|
249
|
+
# Erase part of a layer without affecting others
|
|
250
|
+
["# Select the layer with the mistake",
|
|
251
|
+
"layer_to_fix = image.get_layers()[1]",
|
|
252
|
+
"drawable = layer_to_fix",
|
|
253
|
+
|
|
254
|
+
"# Select area to clear",
|
|
255
|
+
"Gimp.Image.select_rectangle(image, Gimp.ChannelOps.REPLACE, x, y, width, height)",
|
|
256
|
+
|
|
257
|
+
"# Clear selection (makes it transparent)",
|
|
258
|
+
"Gimp.Drawable.edit_clear(drawable)",
|
|
259
|
+
|
|
260
|
+
"# Redraw correctly",
|
|
261
|
+
"Gimp.context_set_foreground(correct_color)",
|
|
262
|
+
"Gimp.Drawable.edit_fill(drawable, Gimp.FillType.FOREGROUND)",
|
|
263
|
+
|
|
264
|
+
"Gimp.Selection.none(image)",
|
|
265
|
+
"Gimp.displays_flush()"]
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Advanced: Using Masks and Selections
|
|
271
|
+
|
|
272
|
+
### Layer Masks for Non-Destructive Editing
|
|
273
|
+
```python
|
|
274
|
+
# Add a mask to control visibility
|
|
275
|
+
["mask = Gimp.LayerMask.new(layer, Gimp.AddMaskType.WHITE)",
|
|
276
|
+
"layer.add_mask(mask)",
|
|
277
|
+
"# Now paint on mask to hide/show parts"]
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Selection-Based Operations
|
|
281
|
+
```python
|
|
282
|
+
# Use selections for precise control
|
|
283
|
+
["# Create selection",
|
|
284
|
+
"Gimp.Image.select_ellipse(image, Gimp.ChannelOps.REPLACE, x, y, w, h)",
|
|
285
|
+
|
|
286
|
+
"# Fill selection (NO feathering by default for sharp, clean edges)",
|
|
287
|
+
"Gimp.Drawable.edit_fill(drawable, Gimp.FillType.FOREGROUND)",
|
|
288
|
+
|
|
289
|
+
"# CRITICAL: Clear selection",
|
|
290
|
+
"Gimp.Selection.none(image)",
|
|
291
|
+
"Gimp.displays_flush()"]
|
|
292
|
+
|
|
293
|
+
# Only use feathering when specifically needed for artistic effects:
|
|
294
|
+
# ["Gimp.Selection.feather(image, radius)"] # Use ONLY if soft edges are explicitly desired
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Summary: The Professional Workflow
|
|
300
|
+
|
|
301
|
+
The key to success with GIMP MCP:
|
|
302
|
+
|
|
303
|
+
1. **Plan** layer structure first
|
|
304
|
+
2. **Build** incrementally (3-5 operations at a time)
|
|
305
|
+
3. **Validate** after each build phase with `get_image_bitmap()`
|
|
306
|
+
4. **Fix** issues immediately on correct layer
|
|
307
|
+
5. **Continue** only when current phase is correct
|
|
308
|
+
|
|
309
|
+
**Don't treat GIMP like a single canvas - leverage its professional features!**
|
|
310
|
+
|
|
311
|
+
Work like a professional digital artist, not like someone with a single paintbrush on a single canvas.
|