InsaneBump - very handy texture map generator for gimp!

amazing plug in for gimp that i found, generates 3 different normal maps, ao maps, height maps, diffuse, specular etc.
Lets you get amazing results with your textures within minutes!
in the video i show you how to install and export out a texture, also how to implement it into bge using a simple plane, and how to use 4 of the 9 textures on it.
very helpful plug-in, thought you guys might like it as well :D!

can be used for any engine, even cycles providing you set up the nodes correctly!

plugin download + instructions: http://registry.gimp.org/node/28638
.blend preview: https://www.mediafire.com/?rwhejihddi93eam

thanks for watching your support is appreciated!

(the preview image is of a 4 vertice plane, no displacement used!)

That’s really great, with nice results! Thank you.

Beautiful plugin. It made me think if image manipulation could be done straight in blender and I spent half a day - that I should have spent on my game - trying to do image filtering in blender. So I’ll blame that plugin if my game doesn’t come out anytime soon (a pitiful excuse).
It turns out the answer is yes, you can do it. It is a bit slow but I went for clarity over performances.
So, in theory, one could build the entire stack of transformations made by that plugin AND apply the images to the active object.
It won’t be the solution to all problems but it would be cool. Drop image, press button X and (after three hours) voilà, your shaded model is served.

Here’s the test i made (generic kernel filtering framework with a 3x3 sharpening matrix used for the test)

import bpy

class DataBuffer():
    def __init__(self, size):
        self.buffer = [None] * size
    def get(self, index):
        return self.buffer[index]
    def set(self, index, value):
        self.buffer[index] = value

class DataMatrix():
    def __init__(self, rowCount, colCount):
        self.rowCount = rowCount
        self.colCount = colCount
        self.buffer = DataBuffer(rowCount * colCount)
    def getRowCount(self):
        return self.rowCount
    def getColCount(self):
        return self.colCount
    def subscript(self, row, column):
        return (self.colCount * row) + column
    def get(self, row, column):
        index = self.subscript(row, column)
        return self.buffer.get(index)
    def set(self, row, column, value):
        index = self.subscript(row, column)
        self.buffer.set(index, value)
        return self

class Pixel():
    def __init__(self, r, g, b, a):
        self.r = r
        self.g = g
        self.b = b
        self.a = a
    def getRed(self): return self.r
    def getGreen(self): return self.g
    def getBlue(self): return self.b
    def getAlpha(self): return self.a
    def scale(self, value, output):
        if output == None: output = Pixel(0,0,0,0)
        output.r = self.r * value
        output.g = self.g * value
        output.b = self.b * value
        output.a = self.a * value
        return output
    def add(self, that, output):
        if output == None: output = Pixel(0,0,0,0)
        output.r = self.r + that.r
        output.g = self.g + that.g
        output.b = self.b + that.b
        output.a = self.a + that.a
        return output
    def clamp(self, output):
        if output == None: output = Pixel(0,0,0,0)
        output.r = max(0, min(self.r, 1))
        output.b = max(0, min(self.b, 1))
        output.g = max(0, min(self.g, 1))
        output.a = max(0, min(self.a, 1))
        return output
    def __str__(self):
        return "RGBA(%d,%d,%d,%d)" % (self.r, self.g, self.b, self.a)

class ImageData():
    def __init__(self, blenderImage):
        self.image = blenderImage
        self.channels = 4
    def getChannels(self):
        return self.channels
    def getRowCount(self):
        return self.image.size[1]
    def getColCount(self):
        return self.image.size[0]
    def getPixelAt(self, row, col):
        raster = self.image.pixels
        index = (self.getColCount() * row * self.getChannels()) + (col * self.getChannels())
        red = raster[index]
        green = raster[index+1]
        blue = raster[index+2]
        alpha = raster[index+3]
        return Pixel(red, green, blue, alpha)
    def setPixelAt(self, row, col, pixel):
        raster = self.image.pixels
        index = (self.getColCount() * row * self.getChannels()) + (col * self.getChannels())
        raster[index] = pixel.getRed()
        raster[index+1] = pixel.getGreen()
        raster[index+2] = pixel.getBlue()
        raster[index+3] = pixel.getAlpha()
    def getSubImage(self, startrow, startcol, rowcount, colcount,extend=True):
        data = DataMatrix(rowcount, colcount)
        for row in range(startrow, startrow+rowcount):
            for col in range(startcol, startcol+colcount):
                if extend:
                    r = min(self.getRowCount() - 1, max(0, row))
                    c = min(self.getColCount() - 1, max(0, col))
                    pixel = self.getPixelAt(r, c)
                    data.set(row-startrow, col-startcol, pixel)
                else:
                    pixel = self.getPixelAt(row, col)
                    data.set(row-startrow, col-startcol, pixel)
        return data
    def setSubImage(self, startrow, startcol, pixelDataMatrix):
        for row in range(startrow, startrow + pixelDataMatrix.getRowCount()):
            for col in range(startcol, startcol + pixelDataMatrix.getColCount()):
                inputPixel = pixelDataMatrix.get(row, col)
                if (row >= 0) and (row < self.getRowCount()) and (col >= 0) and (col < self.getColCount()):
                    self.setPixelAt(row, col, inputPixel)
    def filter(self, filterFun, destinationImage):
        if destinationImage == None:
            destinationImage = generateImageData(self.image.name, self.getRowCount(), self.getColCount())
        filterFun(self, destinationImage)
        return destinationImage
        pass

class ConvolutionFilter():
    def __init__(self, kernelDataMatrix, opaque=True):
        self.kernel = kernelDataMatrix
        self.opaque = opaque
    def __call__(self, source, destination):
        kernelRows = self.kernel.getRowCount()
        kernelCols = self.kernel.getColCount()
        halfKernelRows = int(kernelRows / 2)
        halfKernelCols = int(kernelCols / 2)
        def applyKernel(region):
            tot = Pixel(0,0,0,0)
            for row in range(0, kernelRows):
                for col in range(0, kernelCols):
                    kernelFactor = self.kernel.get(row, col)
                    regionPixel = region.get(row, col)
                    transformedPixel = regionPixel.scale(kernelFactor, None)
                    tot.add(transformedPixel, tot)
            kernelSize = kernelRows * kernelCols
            tot.clamp(tot)
            return tot
        for row in range(0, source.getRowCount()):
            for col in range(0, source.getColCount()):
                firstRow = row - halfKernelRows
                firstCol = col - halfKernelCols
                sourceRegion = source.getSubImage(firstRow, firstCol, kernelRows, kernelCols)
                convolutionResultPixel = applyKernel(sourceRegion)
                if self.opaque: convolutionResultPixel.a = 1
                destination.setPixelAt(row, col, convolutionResultPixel)
        pass
    pass

def getFirstBlenderImage():
    screen = bpy.context.screen
    areas = screen.areas
    for area in areas:
        areaType = area.type
        if areaType == "IMAGE_EDITOR":
            for space in area.spaces:
                if space.__class__.__name__ == "SpaceImageEditor":
                    return (area, space, ImageData(space.image))
    return None
    pass

def generateImageUid(prefix):
    names = [x.name for x in bpy.data.images]
    newname = prefix
    index = 0
    broken = 1000
    while (newname in names) and (index < broken):
        newname = prefix + str(index)
        index += 1
    if index == broken:
        print("generateImageUid: can't find a uid for an image (that's weird)")
        return None
    else:
        return newname

def generateImageData(prefix, rowcount, colcount):
    uid = generateImageUid(prefix)
    bpy.ops.image.new(name=uid, width=colcount, height=rowcount)
    return ImageData(bpy.data.images.get(uid))

"""
Filter the first image available in the image panel with a 3x3 sharpening Kernel.
Takes ages to complete.
"""
def test():
    imageData = getFirstBlenderImage()
    if imageData == None:
        print("no image found")
        return
    area = imageData[0]
    space = imageData[1]
    image = imageData[2]
    kernel = DataMatrix(3,3)
    kernel.set(0,0,0).set(0,1,-1).set(0,2,0)
    kernel.set(1,0,-1).set(1,1,5).set(1,2,-1)
    kernel.set(2,0,0).set(2,1,-1).set(2,2,0)
    conv = ConvolutionFilter(kernel)
    print("Start")
    newimage = image.filter(conv, None)
    print("End")
    pass

test()

This is great. I would also recommend BIMP http://registry.gimp.org/node/26259

Batch Image Manipulation Plugin, very useful for editing lightmaps and other things!

I can not get to gimp plugin website

Website is down ;/

Up again :wink:

I love this plugin! Here is a screenshot of my basic world for a cave game I am making:
[ATTACH=CONFIG]272756[/ATTACH]
Thanks for the plugin!

Attachments


I found this very useful and I am using linux os

Yes i agree, however i found one flaw in the program that is expressed when the texture is very linear, for example andrew prices realistic texturing tutorial. The brick texture he uses when put through the insane bump plugin leaves a diamond shaped blur across the whole texture. This doesn’t affect the diffuse texture but it does change the normal map making some parts of the texture bumpy when there isn’t meant to be any.

I have problem with IsaneBump on Ubuntu 12.04_amd64

I download the binary: https://gimp-plugin-insanebump.googlecode.com/git/linux/bin/gimp-plugin-insanebump-Ubuntu-1.0.6.tar.gz Extrated and place the file /home/serviteur/.gimp-2.8/plug-ins
When select Filters and then Map, InsaneBump DOSEN’T EXIST
Filters->Map->…

How to solved it?

‘’ excuses me for my bad english’’

Check to make sure you have the execute bit set. (e.g. chmod 755 InsaneBump.py)

I verified it is already executable !

The plugin for Ubuntu (extrated) is: gimp-plugin-insanebump (74.0 ko) not IsaneBump.py

http://code.google.com/p/gimp-plugin-insanebump/wiki/UbuntuInstallation

I wrote jdrussell51 and he have compiled from source for amd 64 bit.
The 64bit Ubuntu 12.04 version of the gimp-plugin-insanebump work now !