python-fu Copy an Image
Question: I've a color list file I read it into a python list and I'd like to create one
(or several) image(s) composed by squares with background color read from file
and as foreground html string of the color (written with white). I.e. I read
#ff0000 from input file then I create a 100x100 square with red background and
a white string "#ff0000" as foreground...and so on for each color in input
file.

This is my script:

    
    
    #!/usr/bin/env python
    from gimpfu import *
    
    def readColors(ifc):
        """Read colors from input file and return a python list with all them"""
        a = []
        fd = open(ifc,"r")
        for i in fd:
            if not i.startswith("//"):#skip comment lines
                a.append(i.rstrip('\n'))
        return a
    
    def rgb2html(col):
        """Converts a color: from (255,255,255) to #ffffff"""
        r,g,b = col
        return "#%x%x%x" % (r,g,b)
    
    def html2rgb(col):
        """Converts a color: from #ffffff to (255,255,255)"""
        s=col.strip('#')
        r=int(s[:2],16)
        g=int(s[2:4],16)
        b=int(s[4:6],16)
        return r,g,b
    
    def nextColor():
        """Gets next html color from color list"""
        col = nextColor.array[nextColor.counter]
        nextColor.counter +=1
        return col
    
    def isNextColor():
        """Is there another color or list is over?"""
        return nextColor.counter<isNextColor.colorslenght
    
    def isPageEnded(y,YSIZE):
        """Is there enough room to draw another square?"""
        return (y+100)>=YSIZE
    
    def newPage(XSIZE,YSIZE):
        """Returns a new image"""
        return gimp.Image(XSIZE,YSIZE,RGB)      
    
    def createImage(color,text):
        """Draws a square filled with color and white color text. It works!"""
        gimp.set_foreground((255,255,255))#text color
        gimp.set_background(color)        #background color
        image = gimp.Image(100,100,RGB)
        back = gimp.Layer(image,"font",100,100,RGB_IMAGE,100,NORMAL_MODE)   
        image.add_layer(back,1)
        back.fill(BACKGROUND_FILL)
        lay = back.copy()
        lay.name = "font"
        image.add_layer(lay,0)
        lay = pdb.gimp_text_fontname(image,None,2,100/4,text,2,True,18,PIXELS,"Sans")   
        image.merge_down(lay, NORMAL_MODE)
        image.flatten() 
        return image
    
    def drawRect(image,x,y):
        """Here I'd like to copy the result of createImage at current x,y position of current image. It doesn't work!"""
        text  = nextColor()
        color = html2rgb(text)  
        img = createImage(color,text)
        drawable = pdb.gimp_image_active_drawable(image)    
        image.disable_undo()
        pdb.gimp_selection_none(image)
        pdb.gimp_image_select_rectangle(image, 2, x, y, 100, 100)   
        if pdb.gimp_edit_named_copy_visible(img, "buffer"):             
            floating_sel = pdb.gimp_edit_named_paste(drawable, "buffer", TRUE)
            pdb.gimp_selection_none(image)
            image.flatten() 
            gimp.Display(image)#to debug
            image.enable_undo()
    
    def savePage(image,directory,filename):
        """Saves composed image to filename"""
        drawable = pdb.gimp_image_active_drawable(image)
        pdb.file_png_save(image, drawable, directory+"\\"+filename, filename, 0,9,1,0,0,1,1)
    
    
    def draw(ifile,savedir,prefix):
        """Main method. it manage page's room, slicing it in several 100x100 squares"""
        YSIZE = 1000
        XSIZE = 1000
        x = y = pc = 0
        colorArray = readColors(ifile)
        nextColor.counter = 0
        nextColor.array = colorArray 
        isNextColor.colorslenght = len(colorArray)
        pdb.gimp_context_push()
        image = newPage(XSIZE,YSIZE)
        while(isNextColor()):
            drawRect(image,x,y)
            x += 100        # move to next column
            if x+100>=XSIZE:#move to next row
                x = 0
                y += 100
            if isPageEnded(y,YSIZE):
                savePage(image,savedir,prefix+str(pc)+".png")
                gimp.Display(image)#to debug
                pc += 1
                image = newPage(XSIZE,YSIZE)
                x = 0
                y = 0
        savePage(image,savedir,prefix+str(pc)+".png")#save last page
        pdb.gimp_context_pop()
    
    ifc = '<path to color list file>\\colors.txt'
    ofc = '<path to output directory>\\palette'
    prefix = 'table' #prefix for each file(i.e.: table0.png, table1.png...)
    
    draw(ifc,ofc,prefix) #main method call
    

My current problem is with drawRect method. I can't copy image returned by
createImage method at coords x,y of bigger image in drawRect method. In
drawRect method I tried to used gimp's "copy into selection": select an area,
and paste in it stuff copied from another image. But I have a trouble with
layers and I can't get image copied at right position.

Just for completeness this are few lines from ifc file:

    
    
    #b6ffff
    #f079f3
    #9979f3
    #79c2f3
    #7a79f3
    #79f380
    #f3799a
    

Thanks in advance for any help.

Alberto


Answer: Maybe it could be useful for someone else (it must be saved as "draw-
colors.py" and copied to GIMP 2/lib/gimp/2.0/plug-ins folder):

    
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from gimpfu import *
    
    def readColors(ifile):
        """Read colors from input file and return a python list with all them"""
        a = []
        fd = open(ifile,"r")
        for i in fd:
            if not i.startswith('//'):
                a.append(i)
        return a
    
    def rgb2html(col):
        """Converts a color: from (255,255,255) to #ffffff"""
        r,g,b = col
        return "#%x%x%x" % (r,g,b)
    
    def html2rgb(col):
        """Converts a color: from #ffffff to (255,255,255)"""
        s=col.strip('#')
        r=int(s[:2],16)
        g=int(s[2:4],16)
        b=int(s[4:6],16)
        return r,g,b
    
    def nextColor():
        """Gets next html color from color list"""
        col = html2rgb(nextColor.array[nextColor.counter])
        nextColor.counter +=1
        return col
    
    def isNextColor():  
        """Is there another color or list is over?"""
        return nextColor.counter<isNextColor.colorslenght
    
    def isPageEnded(y,sizey):
        """Is there enough room to draw another square?"""
        return (y+100)>=sizey
    
    def newPage(sizex,sizey):       
        """Returns a new image"""
        image = pdb.gimp_image_new(sizex, sizey, RGB)
        layer = pdb.gimp_layer_new(image, sizex, sizey, RGB, "layer", 0, 0)
        pdb.gimp_image_add_layer(image, layer, 0)
        drw = pdb.gimp_image_active_drawable(image)
        pdb.gimp_context_set_background((255,255,255))
        pdb.gimp_drawable_fill(drw, BACKGROUND_FILL)
        pdb.gimp_context_set_brush('Circle (01)')
        return image
    
    def savePage(image,filename):
        """Saves composed image to filename"""
        layers = image.layers
        last_layer = len(layers)-1
        try:
            disable=pdb.gimp_image_undo_disable(image)
            pdb.gimp_layer_add_alpha(layers[0])
            pdb.plug_in_colortoalpha(image,image.active_layer,(0,0,0))
            layer = pdb.gimp_image_merge_visible_layers(image, 1)
            enable = pdb.gimp_image_undo_enable(image)
            pdb.file_png_save(image, image.active_layer, filename, filename, 0,9,1,0,0,1,1)
        except Exception as e:
            raise e
    
    def drawRect(x,y,color,image):
        """draw a single square"""
        text = rgb2html(color)
        pdb.gimp_image_select_rectangle(image, 2, x, y, 100, 100)
        pdb.gimp_context_set_background(color)
        pdb.gimp_edit_fill(image.active_layer, 1)
        try:
            text_layer = pdb.gimp_text_fontname(image, None, x, y+(100/2), text, 2, 1, 18, 0, "Sans")
            pdb.gimp_image_merge_down(image, text_layer, 0)
        except Exception as e:
            raise e 
    
    def draw(ifile,odir,prefix,sizex,sizey):
        """Main method. it manage page's room, slicing it in several 100x100 squares"""
        colorArray = readColors(ifile)  
        nextColor.counter = 0
        nextColor.array = colorArray
        isNextColor.colorslenght = len(colorArray)  
        pc = x = y = 0
        image = newPage(sizex,sizey)
        try:
            while(isNextColor()):
                pdb.gimp_context_push()
                drawRect(x,y,nextColor(),image)
                x += 100#cambia colonna
                if x+100>=sizex:#cambia riga
                    x = 0
                    y += 100
                if isPageEnded(y,sizey):#salva pagina
                    savePage(image,odir+'\\'+prefix+str(pc)+".png")
                    pc += 1
                    image = newPage(sizex,sizey)
                    x = y = 0
                savePage(image,odir+'\\'+prefix+str(pc)+".png")
                pdb.gimp_context_pop()
        except Exception as e:
            raise e
    
    register(
        "draw-colors",
        N_("Create a color map from a text color file"),
        "Create a color map from a text color file",
        "Alberto",
        "@Copyright Alberto 2014",
        "2014/10/21",
        N_("Draw Colors..."),
        "",
        [
            (PF_FILE, "ifile", N_("Color input file:"), 'default\\input\\colorfile\\path\\colorlist.txt'),
    
            (PF_DIRNAME, "odir", N_("Path for png export:"), 'default\\output\\path'),
            (PF_STRING, "prefix",  N_("Filename prefix for export:"),  "table"),
            (PF_INT8, "sizex", N_("Image's x size:"), 1024),
            (PF_INT8, "sizey", N_("Image's y size:"), 1024)
        ],
        [],
        draw,  #main method call
        menu="<Image>/Filters/Alberto",
        domain=("gimp20-python", gimp.locale_directory)
        )
    
    main()  
    

Output example: ![enter image description
here](http://i.stack.imgur.com/ZLhHn.png)

