Blending in Images into Mockups automatically - kaiserart -  03-28-2024
 
 
Hello Guys, 
 
I am currently setting up an online shop where i have mockups of digital art. 
I am relatively new to gimp but i am fairly trusted with scripting/coding. 
I already managed to write a plugin which rescales a file to several formats. 
 
Now i want to fit an image into the empty mockups. Since i dont want to waste hours doing that manually, i want to automate this. 
 
Example: 
1. I have my blank Mockup Image 
2. I have my image which does not yet fit into the mockup space 
3. Now i have to insert the image into the mockup image 
4. Now i have to rescale and move the image to the mockup space and make it blend in perfectly 
5. Save the mockup with the inserted image 
 
I want to automate this procedure so i can chose a set of images and then they get inserted into different mockups automatically. 
Is there any function/plugin like this? 
If no is it possible to create a fu-python plugin myself to achieve this? 
Basically the mockup does not change. The empty space will always have the same position and size. I just have to fit the image to it. 
 
Thanks in advance if anyone can help me! 
 
Best Regards 
Daniel
 
 
 
RE: Blending in Images into Mockups automatically - Ofnuts -  03-28-2024
 
 
 (03-28-2024, 11:55 AM)kaiserart Wrote:  Is there any function/plugin like this? 
If no is it possible to create a fu-python plugin myself to achieve this? 
Basically the mockup does not change. The empty space will always have the same position and size. I just have to fit the image to it. 
- None I know of
 
 
- Yes
 
 
- You probably want to keep the mockup as an XCF mark the empty space with a layer at the right size/position
 
  
You can also do this with ImageMagick compose but you have to find an external way to remember the size/position of the empty space.
 
 
 
RE: Blending in Images into Mockups automatically - kaiserart -  03-28-2024
 
 
 (03-28-2024, 12:06 PM)Ofnuts Wrote:   (03-28-2024, 11:55 AM)kaiserart Wrote:  Is there any function/plugin like this? 
If no is it possible to create a fu-python plugin myself to achieve this? 
Basically the mockup does not change. The empty space will always have the same position and size. I just have to fit the image to it. 
- None I know of
 
 
- Yes
 
 
- You probably want to keep the mockup as an XCF mark the empty space with a layer at the right size/position
 
  
You can also do this with ImageMagick compose but you have to find an external way to remember the size/position of the empty space. 
 
Thanks for your reply. I managed to create a plugin for myself which iterates through every image in a folder and then through every mockup in a folder. 
Then scales and positions the image according to the mockup and create a blurred shadow around it to make it more seamless. 
 
Still i have one more question. 
When the script finishes actually successfully it says in a GIMP Message: 
 
"Unable to run GimpPdbProgress callback. The corresponding plug-in may have crashed." 
 
Here is my Script (it is rather rudimental, also with absolute paths): 
 
Code: 
 from gimpfu import * 
import os 
 
def set_stroke_params(): 
    # Set opacity to 100% 
    pdb.gimp_context_set_opacity(100) 
 
    # Set paint mode to NORMAL 
    pdb.gimp_context_set_paint_mode(0)  # NORMAL mode 
 
    # Set paint method to GRAYA (this is the default) 
    pdb.gimp_context_set_paint_method("gimp-paintbrush")  # GRAYA method 
 
    # Set stroke method to PAINT 
    pdb.gimp_context_set_stroke_method("0")  # PAINT method 
 
    # Set foreground color to black 
    pdb.gimp_context_set_foreground((0, 0, 0))  # Black color 
 
    # Set active brush (assuming you've already defined the brush) 
    brush_name = "Circle (01)" 
    pdb.gimp_context_set_brush(brush_name) 
 
    # Set line width to 10 
    pdb.gimp_context_set_line_width(6) 
 
    # Enable antialiasing 
    pdb.gimp_context_set_antialias(True) 
 
def create_outline_layer(mockup_image, scaled_image): 
    # Create a new layer filled with transparent color 
    outline_layer = pdb.gimp_layer_new(mockup_image, scaled_image.width, scaled_image.height, RGBA_IMAGE, "Outline", 100, NORMAL_MODE) 
    pdb.gimp_image_insert_layer(mockup_image, outline_layer, None, 0) 
 
    return outline_layer 
 
def mockup_scaleandmove_horizontal(image, drawable): 
    mockups = ["WoodFrame_1.jpg", "BlackBorder_1.jpg", "Gaming_1.jpg", "Gaming_2.jpg", "LivingRoom_1.jpg"] 
    pos_x = [295, 113, 212, 303, 163] 
    pos_y = [611, 236, 112, 171, 115] 
    scale_x = [1461, 801, 492, 436, 699] 
    scale_y = [850, 540, 290, 270, 435] 
    mockup_folder_path = "C:/Users/Daniel Kunz/Desktop/MidJourney/Mockups/Horizontal/Frontal" 
    original_folder_path = "C:/Users/Daniel Kunz/Desktop/MidJourney/NewArt" 
    mockup_image_path = "" 
    original_image_path = "" 
     
    # Iterate through each new file 
    for filename_original in os.listdir(original_folder_path): 
        # Check if it's a file 
        if os.path.isfile(os.path.join(original_folder_path, filename_original)): 
            original_image_path = original_folder_path + "/" + filename_original 
            # Iterate through each mockup 
            for index, mockup in enumerate(mockups): 
                # Iterate through each file in the folder 
                for filename_mockup in os.listdir(mockup_folder_path): 
                    # Check if it's a file 
                    if os.path.isfile(os.path.join(mockup_folder_path, filename_mockup)): 
                        if filename_mockup == mockup: 
                            # Set Mockup Image Path 
                            mockup_image_path = mockup_folder_path + "/" + filename_mockup 
                            # Load the Mockup Image 
                            mockup_image = pdb.gimp_file_load(mockup_image_path, mockup_image_path) 
 
                            # Load the Original Image 
                            original_image = pdb.gimp_file_load(original_image_path, original_image_path) 
 
                            # Resize the original image to fit the mockup 
                            pdb.gimp_image_scale(original_image, scale_x[index], scale_y[index]) 
 
                            # Create a new layer in the mockup image 
                            layer = pdb.gimp_layer_new_from_drawable(original_image.active_drawable, mockup_image) 
 
                            # Add the layer to the mockup image 
                            pdb.gimp_image_insert_layer(mockup_image, layer, None, 0) 
 
                            # Move the layer to the fixed position 
                            pdb.gimp_layer_translate(layer, pos_x[index], pos_y[index]) 
                             
                            # Create a new layer with only the outline of the selection 
                            outline_layer = create_outline_layer(mockup_image, original_image) 
                            # Move the layer to the fixed position 
                            pdb.gimp_layer_translate(outline_layer, pos_x[index], pos_y[index]) 
                            # Select the outline 
                            pdb.gimp_selection_all(outline_layer.image) 
                            # Stroke the selection to draw a line around it 
                            set_stroke_params() 
                            pdb.gimp_drawable_edit_stroke_selection(outline_layer) 
                            # Apply Gaussian blur to the outline layer 
                            pdb.plug_in_gauss(mockup_image, outline_layer, 10, 10, 1) 
                            # Merge the blurred stroke layer with the original layer 
                            # Merge visible layers 
                            merged_layer = pdb.gimp_image_merge_visible_layers(mockup_image, CLIP_TO_IMAGE) 
                            #pdb.gimp_image_merge_down(mockup_image, outline_layer, EXPAND_AS_NECESSARY) 
 
                            # Save the merged image 
                            output_filename = filename_original[:-4] + filename_mockup + ".jpg" 
                            output_foldername = "{}".format(filename_original[:-4]) 
                            output_folder = "C:/Users/Daniel Kunz/Desktop/MidJourney/Images/NewMockups/" + output_foldername 
                            # Check if the directory already exists 
                            if not os.path.exists(output_folder): 
                                # If it doesn't exist, create the directory 
                                os.makedirs(output_folder) 
                            filename = os.path.join(output_folder, output_filename[:-4]) 
                            pdb.gimp_file_save(mockup_image, merged_layer, filename, filename) 
 
                            # Close the images to conserve memory 
                            pdb.gimp_image_delete(mockup_image) 
                            pdb.gimp_image_delete(original_image) 
             
    # Notify user 
    gimp.message("Images rescaled, stroke painted, and saved successfully!") 
 
register( 
    "python_fu_mockup_scaleandmove_horizontal", 
    "Rescale, paint stroke, and save images", 
    "Rescale the input image into 5 different sizes, paint a stroke around the scaled and moved original image, and save them with DPI set to 300.", 
    "Daniel Kunz", 
    "Daniel Kunz", 
    "2024", 
    "<Image>/Filters/Mockup ScaleAndMove Horizontal", 
    "", 
    [], 
    [], 
    mockup_scaleandmove_horizontal) 
 
main()
  
 
 
 
RE: Blending in Images into Mockups automatically - Ofnuts -  03-28-2024
 
 
No idea...  
 
Otherwise very many oddities... how much of this comes from ChatGPT or equivalent?
 
 
 
RE: Blending in Images into Mockups automatically - kaiserart -  03-28-2024
 
 
 (03-28-2024, 09:14 PM)Ofnuts Wrote:  No idea...  
 
Otherwise very many oddities... how much of this comes from ChatGPT or equivalent? 
 
I used it to get the right commands for the image transformations and the general usage for a gimp plugin, but noticed that it used some outdated ones. And also wrong sometimes so it was a lot of adjusting manually... 
The rest i programmed myself.
 
 
 
RE: Blending in Images into Mockups automatically - Ofnuts -  03-29-2024
 
 
Then some suggestions: 
 
Use the new form of registration (menu entry and menu location in distinct parameters) and avoid the useless image/drawable parameters 
 
Code: 
 def mockup_scaleandmove_horizontal():  # No arguments until you add useful ones such as inpout/output directories 
    # Current code goes here 
 
register( 
   "python_fu_mockup_scaleandmove_horizontal", 
   "Rescale, paint stroke, and save images", 
   "Rescale the input image into 5 different sizes, paint a stroke around the scaled and moved original image, and save them with DPI set to 300.", 
   "Daniel Kunz", 
   "Daniel Kunz", 
   "2024", 
   "Mockup ScaleAndMove Horizontal", 
   "", 
   [], 
   [], 
   mockup_scaleandmove_horizontal, 
   menu="<Image>/Filters/")
  
 
Avoid the "parallel arrays" "anti-pattern", use an array of tuples: 
 
Code: 
    mockups = [ 
       ("WoodFrame_1.jpg",     295,  611,  1461, 850), 
       ("BlackBorder_1.jpg",   113,  236,  801,  540), 
       ("Gaming_1.jpg",        212,  112,  492,  290), 
       ("Gaming_2.jpg",        303,  171,  436,  270), 
       ("LivingRoom_1.jpg"     163,  115,  699,  435), 
       ]
  
 
Then iterate and unpack the mockups: 
 
Code: 
 for index, mockup in enumerate(mockups): 
    pdb.gimp_image_scale(original_image, scale_x[index], scale_y[index]) 
    pdb.gimp_layer_translate(outline_layer, pos_x[index], pos_y[index])
  
 
becomes: 
 
Code: 
 for mockup, pos_x, pos_y, scale_x, scale_y in mockups: 
    pdb.gimp_image_scale(original_image, scale_x, scale_y) 
    pdb.gimp_layer_translate(outline_layer, pos_x, pos_y)
  
 
Instead of loading two separate images, and copying a layer from the second to the first, you can use pdb.gimp_file_load_layer(image, filename) to load a file directly as a layer (that you still need to insert at the right position). 
 
Since your code changes the context (the whole of set_stroke_params() (which in passing you can call only once outside of the loops)), you can bracket the whole script between pdb.gimp-context-push() and pdb.gimp-context-pop() calls to restore the initial context when done. 
 
Use os.path.splitext() to extract the root name of a file, and os.path.join() to create a full path from directories and file names. 
 
Code: 
 output_foldername = "{}".format(filename_original[:-4])
  
is definitely the weirdest line of code, because it is just a very complicated way to do 
Code: 
 output_foldername = filename_original[:-4]
  
or more properly (see above): 
Code: 
 output_foldername = os.path.splitext(filename_original)[0]
  
 
 
 
RE: Blending in Images into Mockups automatically - kaiserart -  04-02-2024
 
 
 (03-29-2024, 08:20 AM)Ofnuts Wrote:  Then some suggestions: 
 
Use the new form of registration (menu entry and menu location in distinct parameters) and avoid the useless image/drawable parameters 
 
Code: 
 def mockup_scaleandmove_horizontal():  # No arguments until you add useful ones such as inpout/output directories 
    # Current code goes here 
 
register( 
   "python_fu_mockup_scaleandmove_horizontal", 
   "Rescale, paint stroke, and save images", 
   "Rescale the input image into 5 different sizes, paint a stroke around the scaled and moved original image, and save them with DPI set to 300.", 
   "Daniel Kunz", 
   "Daniel Kunz", 
   "2024", 
   "Mockup ScaleAndMove Horizontal", 
   "", 
   [], 
   [], 
   mockup_scaleandmove_horizontal, 
   menu="<Image>/Filters/")
  
 
Avoid the "parallel arrays" "anti-pattern", use an array of tuples: 
 
Code: 
    mockups = [ 
       ("WoodFrame_1.jpg",     295,  611,  1461, 850), 
       ("BlackBorder_1.jpg",   113,  236,  801,  540), 
       ("Gaming_1.jpg",        212,  112,  492,  290), 
       ("Gaming_2.jpg",        303,  171,  436,  270), 
       ("LivingRoom_1.jpg"     163,  115,  699,  435), 
       ]
  
 
Then iterate and unpack the mockups: 
 
Code: 
 for index, mockup in enumerate(mockups): 
    pdb.gimp_image_scale(original_image, scale_x[index], scale_y[index]) 
    pdb.gimp_layer_translate(outline_layer, pos_x[index], pos_y[index])
  
 
becomes: 
 
Code: 
 for mockup, pos_x, pos_y, scale_x, scale_y in mockups: 
    pdb.gimp_image_scale(original_image, scale_x, scale_y) 
    pdb.gimp_layer_translate(outline_layer, pos_x, pos_y)
  
 
Instead of loading two separate images, and copying a layer from the second to the first, you can use pdb.gimp_file_load_layer(image, filename) to load a file directly as a layer (that you still need to insert at the right position). 
 
Since your code changes the context (the whole of set_stroke_params() (which in passing you can call only once outside of the loops)), you can bracket the whole script between pdb.gimp-context-push() and pdb.gimp-context-pop() calls to restore the initial context when done. 
 
Use os.path.splitext() to extract the root name of a file, and os.path.join() to create a full path from directories and file names. 
 
Code: 
 output_foldername = "{}".format(filename_original[:-4])
  
is definitely the weirdest line of code, because it is just a very complicated way to do 
Code: 
 output_foldername = filename_original[:-4]
  
or more properly (see above): 
Code: 
 output_foldername = os.path.splitext(filename_original)[0]
  
 
 
Thank you so much. This made the code so much clearer and made me understand the gimp scripting better! 
It works perfectly...
 
 
 
 |