I spent some time figuring out memblocks for image editing a while ago and came up with some pretty cool stuff.
I've started working on a library of code that allows you to create and edit DBP images/textures through the use of memblocks, without actually having to understand memblocks to use it. This hasn't been tested in DBC yet, only DBP.
Library Code:
remstart
======================================================================================================================
=====================================SYNCAIDIUS' MEMBLOCK IMAGE MANIPULATION LIBRARY V1.1=============================
======================================================================================================================
Feel free to use this code however you wish, whether that be for free or commercial games or programs.
remend
//Creates a new memblock image filled with the specified colour.
function IMG_MAKE(width as integer, height as integer, colour as dword)
mem = FREE_MEMBLOCK()
pixels = width*height
bytes = 4+4+4+(pixels*4) //width+height+depth+data
bytePos = 0
make memblock mem,bytes
width = (0<<24) + (0<<16) + (0<<8) + width
height = (0<<24) + (0<<16) + (0<<8) + height
depth = (0<<24) + (0<<16) + (0<<8) + 32
//write image info
write memblock dword mem,bytePos,width : inc bytePos,4
write memblock dword mem,bytePos,height : inc bytePos,4
write memblock dword mem,bytePos,depth : inc bytePos,4
//set every pixel in the image to the specified colour
for pixel = 1 to pixels
write memblock dword mem,bytePos,colour : inc bytePos,4 //set all pixels to the specified 'colour'
next pixel
endfunction mem
//converts a DBP image into a memblock image. The function will also delete the image that was used, if the delete parameter is set to 1.
function IMG_CONVERT(img as integer, delete as boolean)
mem = FREE_MEMBLOCK()
make memblock from image mem,img
//check if the image should be deleted (since its now inside a memblock, the coder may not want the image anymore).
if delete = 1
delete image img
endif
endfunction mem
//sets the colour of the specified pixel on a memblock image
function IMG_SET_PIXEL(memblock as byte, x as integer, y as integer, colour as dword)
//get the width and height of the image
width = memblock byte(memblock,0)+256*memblock byte(memblock,1)
height = memblock byte(memblock,4)+256*memblock byte(memblock,5)
if x>-1 and x<width
if y>-1 and y<height
n as double integer
n = (4*((y*width)+x))+12
write memblock dword memblock,n,colour
endif
endif
endfunction
//same as IMAGE_SET_PIXEL except the memblock image width and height have to be entered. This speeds things up a little if you have many pixels to write and already know the image width/height)
function IMG_SET_PIXEL2(memblock as byte, x as integer, y as integer, width as integer, height as integer, colour as dword)
if x>-1 and x<width
if y>-1 and y<height
n as double integer
n = (4*((y*width)+x))+12
write memblock dword memblock,n,colour
endif
endif
endfunction
//returns the colour of the specified pixel as a dword
function IMG_GET_PIXEL(memblock as byte, x as integer, y as integer)
width = memblock byte(memblock,0)+256*memblock byte(memblock,1)
height = memblock byte(memblock,4)+256*memblock byte(memblock,5)
pixel = IMG_RGBA(255,255,255,255)
if x>-1 and x<width
if y>-1 and y<height
n as double integer
n = (4*((y*width)+x))+12
pixel = memblock dword(memblock,n)
endif
endif
endfunction pixel
//same as IMAGE_GET_PIXEL except the width and height have to be entered. This speeds things up a little if you have many pixels to read and already know the image width/height)
function IMG_GET_PIXEL2(memblock as byte, x as integer, y as integer, width as integer, height as integer)
pixel = IMG_RGBA(255,255,255,255)
if x>-1 and x<width
if y>-1 and y<height
n as double integer
n = (4*((y*width)+x))+12
pixel = memblock dword(memblock,n)
endif
endif
endfunction pixel
//creates or updates a DBP image with the contents of a memblock image
function IMG_UPDATE(memblock as byte, img as integer)
make image from memblock img,memblock
endfunction
//sets the whole image to a single colour
function IMG_CLEAR(mem as byte, colour as dword)
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
for x = 0 to (width-1)
for y = 0 to (height-1)
IMG_SET_PIXEL2(mem,x,y,width,height,colour)
next y
next x
endfunction
//does exactly the same as DELETE MEMBLOCK, just uses the image library naming convention instead.
function IMG_DELETE(mem as byte)
delete memblock mem
endfunction
//Pastes a normal image into a memblock image.
function IMG_PASTE_IMAGE(mem as integer, srcImg as integer, x as integer, y as integer)
tempMem = FREE_MEMBLOCK() //temp memblock for the image that will be pasted
make memblock from image tempMem,srcImg
//width and height of source memblock
imgWidth = memblock byte(tempMem,0)+256*memblock byte(tempMem,1)
imgHeight = memblock byte(tempMem,4)+256*memblock byte(tempMem,5)
//width and height of destination memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
for px = 0 to (imgWidth-1)
for py = 0 to (imgHeight-1)
col = IMG_GET_PIXEL2(tempMem,px,py,imgWidth,imgHeight)
IMG_SET_PIXEL2(mem,x+px,y+py,width,height,col)
next py
next px
//delete the temp memblock
delete memblock tempMem
endfunction
//paste a memblock image into another memblock image at the specified coords. Also create a function to paste part of one memblock image into another memblock image.
function IMG_PASTE_MEMBLOCK(mem as integer, srcMem as integer, x as integer, y as integer)
//width and height of destination memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//width and height of source memblock (memblock that will be pasted)
widthsrc = memblock byte(srcMem,0)+256*memblock byte(srcMem,1)
heightsrc = memblock byte(srcMem,4)+256*memblock byte(srcMem,5)
for px = 0 to (widthsrc-1)
for py = 0 to (heightsrc-1)
col = IMG_GET_PIXEL2(src,px,py,widthsrc,heightsrc)
IMG_SET_PIXEL2(mem,x+px,y+py,width,height,col)
next py
next px
endfunction
//copies the specified area of one memblock image (source) into another memblock image (destination)
function IMG_PASTE_MEMBLOCK_PART(mem as byte, srcMem as byte, x as integer, y as integer, x2 as integer, y2 as integer, x3 as integer, y3 as integer)
//width and height of destination memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//width and height of source memblock (memblock to copy from)
widthsrc = memblock byte(srcMem,0)+256*memblock byte(srcMem,1)
heightsrc = memblock byte(srcMem,4)+256*memblock byte(srcMem,5)
//get the width and height of the area to be copied
difX = x3 - x2
difY = y3 - y2
for px = 0 to difX
for py = 0 to difY
col = IMG_GET_PIXEL2(srcMem,x2+px,y2+py,widthsrc,heightsrc)
IMG_SET_PIXEL2(mem,x+px,y+py,width,height,col)
next py
next px
endfunction
//draw a solid colour rectangle inside a memblock image
function IMG_DRAW_RECTANGLE(mem as byte, x as integer, y as integer, width as integer, height as integer, colour as dword)
//width and height of destination memblock
memwidth = memblock byte(mem,0)+256*memblock byte(mem,1)
memheight = memblock byte(mem,4)+256*memblock byte(mem,5)
//set rectangle pixels
for px = 0 to (width-1)
for py = 0 to (height-1)
IMG_SET_PIXEL2(mem,x+px,y+py,memwidth,memheight,colour)
next py
next px
endfunction mem
function IMG_DRAW_RECTANGLE_OUTLINE(mem as integer, x as integer, y as integer, width as integer, height as integer, thickness as integer, colour as dword)
//width and height of destination memblock
memwidth = memblock byte(mem,0)+256*memblock byte(mem,1)
memheight = memblock byte(mem,4)+256*memblock byte(mem,5)
//left side
for px = x to x+thickness
for py = y to (y+height)
IMG_SET_PIXEL2(mem,px,py,memwidth,memheight,colour)
next py
next px
//right side
for px = (x+width) to (x+width)-thickness step -1
for py = y to (y+height)
IMG_SET_PIXEL2(mem,px,py,memwidth,memheight,colour)
next py
next px
//top side
for px = x to (x+width)
for py = y to y+thickness
IMG_SET_PIXEL2(mem,px,py,memwidth,memheight,colour)
next py
next px
//bottom side
for px = x to (x+width)
for py = (y+height) to (y+height)-thickness step -1
IMG_SET_PIXEL2(mem,px,py,memwidth,memheight,colour)
next py
next px
endfunction
//draw a line - memblock, x1, y1, x2, y2, line width/thickness, red, green, blue
function IMG_DRAW_LINE(mem as byte, x1 as integer, y1 as integer, x2 as integer, y2 as integer, colour as dword)
//get width and height of memblock image
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
deltax = abs(x2 - x1) // The difference between the x's
deltay = abs(y2 - y1) // The difference between the y's
x = x1 // Start x off at the first pixel
y = y1 // Start y off at the first pixel
numadd = 0
if x2 >= x1 // The x-values are increasing
xinc1 = 1
xinc2 = 1
else // The x-values are decreasing
xinc1 = -1
xinc2 = -1
endif
if y2 >= y1 // The y-values are increasing
yinc1 = 1
yinc2 = 1
else // The y-values are decreasing
yinc1 = -1
yinc2 = -1
endif
if (deltax >= deltay) // There is at least one x-value for every y-value
xinc1 = 0 // Don't change the x when numerator >= denominator
yinc2 = 0 // Don't change the y for every iteration
den = deltax
num = deltax / 2
numadd = deltay
numpixels = deltax // There are more x-values than y-values
else // There is at least one y-value for every x-value
xinc2 = 0 // Don't change the x for every iteration
yinc1 = 0 // Don't change the y when numerator >= denominator
den = deltay
num = deltay / 2
numadd = deltax
numpixels = deltay // There are more y-values than x-values
endif
for curpixel = 0 to numpixels
IMG_SET_PIXEL2(mem,x,y,width,height,colour)
num = num + numadd // Increase the numerator by the top of the fraction
if num >= den // Check if numerator >= denominator
num = num - den // Calculate the new numerator value
x = x + xinc1 // Change the x as appropriate
y = y + yinc1 // Change the y as appropriate
endif
x = x + xinc2 // Change the x as appropriate
y = y + yinc2 // Change the y as appropriate
next curpixel
endfunction
//draws a filled circle
function IMG_DRAW_CIRCLE(mem as byte, x as integer, y as integer, radius as integer, colour as dword)
//get width and height of memblock image
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
dots = radius*(6.28*2)
deg2dot#=360/(dots*1.0)
for f = 0 to radius
for d = 0 to dots
u = sin(d*deg2dot#)*(radius-f)
v = cos(d*deg2dot#)*(radius-f)
IMG_SET_PIXEL2(mem,x+u,y+v,width,height,colour)
next d
next f
endfunction
//draws a circle outline
function IMG_DRAW_CIRCLE_OUTLINE(mem as byte, x as integer, y as integer, radius as integer, dotRate as integer, thickness as integer, colour as dword)
//get width and height of memblock image
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
radians = (6.28/100)*dotRate //how many dots are allowed to make up the circle's border
dots = radius*radians
deg2dot#=360/(dots*1.0)
for t = 0 to thickness
for d = 0 to dots
u = sin(d*deg2dot#)*(radius-t)
v = cos(d*deg2dot#)*(radius-t)
IMG_SET_PIXEL2(mem,x+u,y+v,width,height,colour)
next d
next t
endfunction
//draws part of a circle
function IMG_DRAW_CIRCLE_PART(mem as byte, x as integer, y as integer, radius as integer, fillPercent as integer, cFill as boolean, angle as float, colour as dword)
//get width and height of memblock image
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//calculate circle border dot amount and angle
radians = (6.28/100)*fillPercent //how many dots are allowed to make up the circle's border
dots = radius*radians
deg2dot#=angle/(dots*1.0)
if cFill = 0 //check if the circle is to be filled or not
for d = 0 to dots
u = sin(d*deg2dot#)*radius
v = cos(d*deg2dot#)*radius
IMG_SET_PIXEL2(mem,x+u,y+v,width,height,colour)
next d
else
for f = 0 to radius
for d = 0 to dots
u = sin(d*deg2dot#)*(radius-f)
v = cos(d*deg2dot#)*(radius-f)
IMG_SET_PIXEL2(mem,x+u,y+v,width,height,colour)
next d
next f
endif
endfunction
//converts the input memblock image to a greyscale image
function IMG_GREYSCALE(mem as byte)
//get width and height of memblock image
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
for x = 0 to (width-1)
for y = 0 to (height-1)
col = IMG_GET_PIXEL2(mem,x,y,width,height)
//seperate each pixel colour channel from the col dword value
a=rgba(col)
r=rgbr(col)
g=rgbg(col)
b=rgbb(col)
//calculate the black/white/grey to use
col = (r+g+b)/3 //add rgb together and average out (divide by 3)
IMG_SET_PIXEL2(mem,x,y,width,height,IMG_RGBA(col,col,col,255))
next y
next x
endfunction
//flips a memblock image horizontally
function IMG_FLIP_HORIZONTAL(mem as byte)
//retrieve image width and height from memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//create a temp image memblock of the same size as our image's memblock
temp = IMG_MAKE(width, height, IMG_RGBA(0,0,0,255))
//rewrite the data into the temp memblock, with the x axis flipped
for x = 0 to (width-1)
for y = 0 to (height-1)
nx = width-x
col = IMG_GET_PIXEL2(mem,x,y,width,height)
IMG_SET_PIXEL2(temp,nx,y,width,height,col)
next y
next x
//copy everything from the temp memblock back into our image memblock and delete the temp one.
copy memblock temp,mem,0,0,get memblock size(mem)
delete memblock temp
endfunction
//flips a memblock image vertically
function IMG_FLIP_VERTICAL(mem as byte)
//retrieve image width and height from memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//create a temp image memblock of the same size as our image's memblock
temp = IMG_MAKE(width, height, IMG_RGBA(0,0,0,255))
//rewrite the data into the temp memblock, with the y axis flipped
for x = 0 to (width-1)
for y = 0 to (height-1)
ny = height-y
col = IMG_GET_PIXEL2(mem,x,y,width,height)
IMG_SET_PIXEL2(temp,x,ny,width,height,col)
next y
next x
//copy everything from the temp memblock back into our image memblock and delete the temp one.
copy memblock temp,mem,0,0,get memblock size(mem)
delete memblock temp
endfunction
function IMG_TINT(mem as byte, colour as dword)
//retrieve image width and height from memblock
width = memblock byte(mem,0)+256*memblock byte(mem,1)
height = memblock byte(mem,4)+256*memblock byte(mem,5)
//seperate each tint colour channel from the dword colour value
ta=(colour && 0xFF000000) >> 24 //retrieves bits 24 - 31 from the colour (byte 4). Alpha
tr=(colour && 0x00FF0000) >> 16 //retrieves bits 16 - 23 from the colour (byte 3). Red
tg=(colour && 0x0000FF00) >> 8 //retrieves bits 8 - 15 from the colour (byte 2). Green
tb=(colour && 0x000000FF) //retrieves bits 0 - 7 from the colour (byte 1). Blue
for x = 0 to (width-1)
for y = 0 to (height-1)
col = IMG_GET_PIXEL2(mem,x,y,width,height)
//seperate each pixel colour channel from the col dword value
a=(col && 0xFF000000) >> 24
r=(col && 0x00FF0000) >> 16
g=(col && 0x0000FF00) >> 8
b=(col && 0x000000FF)
//add the tint and pixel colour together, then divide it by 2 to average it.
col = IMG_RGBA((r+tr)/2, (g+tg)/2, (b+tb)/2,(a+ta)/2)
IMG_SET_PIXEL2(mem,x,y,width,height,col)
next y
next x
endfunction
function FREE_MEMBLOCK()
for find = 1 to 255
if memblock exist(find) = 0
exitfunction find
endif
next find
endfunction 0
//converts 4 seperate colour channels into a single DWORD and returns it.
function IMG_RGBA(r as byte, g as byte, b as byte, a as byte)
col = (a<<24) + (r<<16) + (g<<8) + b
endfunction col
So far the library can do the following on a memblock texture:
Create an empty texture filled with the given colour
Draw circle
Draw lines
Flip images
Tint and Greyscale
Edit single pixels (aka draw dots)
Draw circle outlines (and the thickness can be adjusted)
Draw part-circles and part-circle outlines (e.g. a 90 degree piece of a circle or whatever)
copy a DBP or memblock image and paste it into another image
copy part of one image into another image
This is still a work in progress and I still have a lot of things I want to add to it before I can say its complete. A few of these things are:
Image Resizing
Drawing polygons onto a texture (e.g. a hexagon, octogon or other random shape)
Drawing triangles
Gradient boxes, rectangles, triangles, circles and lines
Texture rotation
Text on textures
I've included four examples of what the library can do so far. You don't need any external plugins to use the code.
Here is a few screenshots for those who like pretty pictures:
You are free to use the code as you wish, whether that be for personal or commercial use.