Posted: 28th Apr 2021 13:51
your very welcome
Posted: 10th Feb 2023 2:42
The below program speed tests various methods of flipping an object as follows:
1 using a memblock with getcolour commands
2 using a shader without using draw calls (hence if you was to save the image the changes would not be seen)
3 using Kevin Pocones suggestion and modifying the memblock to retrieve an integer instead of 3 calls to get colours
4 adds the time before with a shader to retrieving the image

not being aware of the command SetSpriteFlip ( iSpriteIndex, horz, vert ) i created the following code
which i hope will help people have a better understanding of memblocks and shaders ive included a test image
+ Code Snippet
// Project: imageManipulation 
// Created: 2023-02-03

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "imageManipulation" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
speedtest as float
//path="raw:"+getreadpath()+"media/"
test=loadimage("test.png"):resettimer() : rem timer here is set to 0 so as speed tests acurate to milliseconds can be displayed
a=createsprite(test)         //reading from left to right and top down a = first sprite
b=createsprite(flip(test,1)) //b second sprite 
c=createsprite(flip(test,2)) //c third sprite
d=createsprite(flip(test,3)) //d fourth sprite
SetSpritePosition(a,20,40)
setspriteposition(b,276,40)
setspriteposition(c,532,40)
setspriteposition(d,776,40)
speedtest1$=str(timer())


createShaderFile("flip.ps")
e_s=LoadSpriteShader("flip.ps") 
f_s=LoadSpriteShader("flip.ps")
g_s=LoadSpriteShader("flip.ps")
h_s=LoadSpriteShader("flip.ps")
resettimer()
e=createSprite(test)  //the second row is for the shader flip the sprite 
SetSpritePosition(e,20,220) //from left to right
SetSpriteShader(e,e_s)

f=createSprite(test)
SetSPritePosition(f,276,220)
SetSpriteShader(f,f_s)

g=createSprite(test)
SetSpritePosition(g,532,220)
SetSpriteShader(g,g_s)

h=createSprite(test)
SetSpritePosition(h,776,220)
SetSpriteShader(h,h_s)

SetShaderConstantByName(e_s, "rot", 0.0, 0.0, 0.0, 0.0 ) //the first two passed values may be set to 1.0 to rotate or 0 not to rotate they may only be 1.0 or 0.0
SetShaderConstantByName(f_s, "rot", 1.0, 0.0, 0.0, 0.0 ) //the first two passed values may be set to 1.0 to rotate or 0 not to rotate
SetShaderConstantByName(g_s, "rot", 0.0, 1.0, 0.0, 0.0 ) //the first two passed values may be set to 1.0 to rotate or 0 not to rotate
SetShaderConstantByName(h_s, "rot", 1.0, 1.0, 0.0, 0.0 ) //the first two passed values may be set to 1.0 to rotate or 0 not to rotate
// the first value passed to the shader is flip on x axis while the secong is the y axis 
swap():render() //swap and render needs to be called prior to get image
newEI=GetImage(getspritex(e),getspritey(e),getspritex(e)+getspritewidth(e),getspritey(e)+getSpriteheight(e)) //here are four more images to be created that make up the bottom 4th row
newFI=GetImage(getspritex(f),getspritey(f),getspritex(f)+getspritewidth(f),getspritey(f)+getSpriteheight(f))
newGI=GetImage(getspritex(g),getspritey(g),getspritex(g)+getspritewidth(g),getspritey(g)+getSpriteheight(g))
newHI=GetImage(getspritex(h),getspritey(h),getspritex(h)+getspritewidth(h),getspritey(h)+getSpriteheight(h))

speedtest=timer()
speedtest2$=str(speedtest)
resetTimer()
newE=createsprite(newEI)
newF=createsprite(newFI)
newG=createsprite(newGI)
newH=createsprite(newHI)
SetSpritePosition(newE,20,580)
SetSpritePosition(newF,276,580)
SetSpritePosition(newG,532,580)
SetSpritePosition(newH,776,580)
speedtest4$=str(timer()+speedtest)

resettimer()
i=createSprite(test)
SetSpritePosition(i,20,400) //the 3rd row demonostrating getint instead of retrieving the colours individually
j=createSprite(flip2(test,1))
SetSPritePosition(j,276,400)
k=createSprite(flip2(test,2))
SetSpritePosition(k,532,400)
l=createSprite(flip2(test,3))
SetSpritePosition(l,776,400)
speedtest3$=(str(timer()))
//SetRawWritePath(getreadpath())
//saveimage(getspriteimageID(h),"testsave.png")
do
    print("flip1="+speedtest1$+"    shader"+speedtest2$+"    flip2="+speedtest3$+"     shader/total="+speedtest4$)
    Sync()
loop

function flip(img as integer,flip as integer)
imgmemblock = CreateMemblockFromImage(img)
newmemblock = CreateMemblockFromImage(img)
local size as integer     
width = GetMemblockInt(imgmemblock,0)
height = GetMemblockInt(imgmemblock,4)
size=abs(width*height)
for y= 0 to height-1
	for x= 0 to width-1 //to 0 step -1
		
		Offset = (12+((y * width) + x) * 4) - 4
		r=GetMemblockByte(imgmemblock,Offset)
		g=GetMemblockByte(imgmemblock,Offset+1)
		b=GetMemblockByte(imgmemblock,Offset+2)
		a=GetMemblockByte(imgmemblock,Offset+3)
		color#=(r+g+b) 
		if flip=1
			xx=width-1 -x
			Offset = (12+((y * width) + xx) * 4) - 4
		elseif flip=2
			yy=height-1 -y
			Offset = (12+((yy * width) + x) * 4) - 4
		else
			xx=width-1 -x
			yy=height-1-y	
			Offset = (12+((yy * width) + xx) * 4) - 4
		endif		
		SetMemblockByte(newmemblock,Offset,r)
		setMemblockByte(newmemblock,Offset+1,g)
		setMemblockByte(newmemblock,Offset+2,b)
		setMemblockByte(newmemblock,Offset+3,a)
	next x
next y	
newImg=CreateImageFromMemblock(newmemblock)
deletememblock(newmemblock)
deletememblock(imgmemblock)
endfunction newimg 

function createShaderFile(name$ as string)
 
fw=OpenToWrite(name$)
WriteLine(fw,"#ifdef GL_ES")
WriteLine(fw,"precision mediump float;")
WriteLine(fw,"precision mediump int;")
WriteLine(fw,"#endif")
WriteLine(fw,"#define PROCESSING_TEXTURE_SHADER")
WriteLine(fw,"varying mediump vec2 uvVarying;")
WriteLine(fw,"uniform sampler2D texture0;")
WriteLine(fw,"uniform vec2 rot;")
WriteLine(fw,"void main(void)")
WriteLine(fw,"{")
//WriteLine(fw,"  vec2 p = uvVarying;")
WriteLine(fw,"  vec2 p = mix(uvVarying, rot - uvVarying, rot);")
//WriteLine(fw,"  if (rot.x ==1.0)")
//WriteLine(fw,"  {p.x=rot.x-p.x;}")   ///p.x -= mod(p.x, 1.0 / pixels.x);")
//WriteLine(fw,"  if (rot.y==1.0)")
//WriteLine(fw,"  {p.y=rot.y-p.y;}")   ////p.y -= mod(p.y, 1.0 / pixels.y);")
WriteLine(fw,"  vec3 col = texture2D(texture0, p).rgb;")
WriteLine(fw,"  gl_FragColor = vec4(col, 1.0);")
WriteLine(fw,"}")
CloseFile(fw)
endfunction

function flip2(img as integer,flip as integer)
imgmemblock = CreateMemblockFromImage(img)
newmemblock = CreateMemblockFromImage(img)
local size as integer    
width = GetMemblockInt(imgmemblock,0)
height = GetMemblockInt(imgmemblock,4)
size=abs(width*height)
for y= 0 to height-1
 
    SrcOffset = (12+ ((y * width) *4))
 
    for x= 0 to width-1 //to 0 step -1
        
         // Read Source pixel  
        ARGB=GetMemblockInt(imgmemblock,SrcOffset)
    // move to the next pixel along this row
       SrcOffset=SrcOffset+4
 
        if flip=1
            xx=width-1 -x
            Offset = (12+((y * width) + xx) * 4) - 4
        elseif flip=2
            yy=height-1 -y
            Offset = (12+((yy * width) + x) * 4) - 4
        else
            xx=width-1 -x
            yy=height-1-y   
            Offset = (12+((yy * width) + xx) * 4) - 4
        endif      
 
        SetMemblockInt(newmemblock,Offset,ARGB)
    next x
next y  
newImg=CreateImageFromMemblock(newmemblock)
deletememblock(newmemblock)
deletememblock(imgmemblock)
endfunction newimg 
Posted: 19th Feb 2023 14:49
A new take on "Hello World" with a kind of matrix effect
+ Code Snippet
// Project: TextFun 
// Created: 2016-12-29

//program creates a string of characters and subtracts the length and asci equivalent of each character
//within the text. A matrix kinda effect that then appends a letter at a time to the end, as if the program
//is deciphering a code string but just uses some asci and string manipulation


// show all errors
SetErrorMode(2)
#constant setAmmount 50 
// set window properties
SetWindowTitle( "TextFun" )
SetWindowSize( 1024, 768, 0 )

// set display properties
SetVirtualResolution( 1024, 768 )
SetOrientationAllowed( 1, 1, 1, 1 )
global CodeString$="HelloWorld": ammount=setAmmount :Global decipher$ :reversed$ as string
Words as string  :global dontDo as integer
Words=makeRandomString("",48,64,0,ammount)   
//Words=makeNewString("This is hello World text This is hello World text This is hello World text This is hello World text ",0):ammount=len(Words)
dontDo=0:global txt1 as integer
txt1=CreateText(Words)
SetTextSize(txt1,Random(50,60))
SetTextColor(txt1,0,255,0,255)
SetTextPosition(txt1,10,10)
SetTextMaxWidth( txt1,1020 ) 
sync()
//Words=makeRandomString("",48,64,0,ammount)
start_time = GetMilliseconds()
repeat
	reversed$=reverseString(decipher$) //as decipger is created in reverse order this just places in correct order
//print(dontdo)	
//Print(reversed$)
//Print(codeString$)
	current_time = GetMilliseconds()
	if current_time - start_time > 25 
		start_time = current_time
		if dontDo=0 and reversed$ <> words
			dontdo=1
			//if reverseString(decipher$) <> words then 
			Words=subtractAscii(Words)
			if ammount< len(codeString$)
				decipher$=decipher$+right(CodeString$,1) //add last character from codestring to decipher
				codeString$=left(codeString$,len(codeString$)-1) //subtracts from codestring a character
				ammount=setAmmount
		    endif
		    SetTextString(txt1,Words)
		elseif reversed$ <> words
			if ammount>-1  
				dec ammount
				Words = makeRandomString("",48,64,0,ammount)
				SetTextColor(txt1,0,255,0,255)
				colorDeciphered(txt1,decipher$)
			endif
			
			SetTextString(txt1,Words)
			dontDo=0
		endif
	endif	
Sync()
until GetRawKeyState(32)
end

function subtractAscii (word as string)
//Each letter or a string passed is replaced with the character 1 less than previous
newWord as String
newWord=""
length=len(word)
empty=0
for i = 1 to length //-len(decipher$) //to 1 step -1
		a$=Mid(word,i,1)
		a=asc(a$) 
		if a$<>chr(32) 
			a=a-1
		else
			empty=empty+1
		endif
		//if empty=length then dontDo=1
		newWord=newWord+chr(a)
next i	
newword=newword+reverseString(decipher$)
endfunction	newWord

function makeNewString(s$ as string, n as integer)
	//work in progress
	r$="":length=len(s$)-n
	if length >0
		r$=left(s$,length)
	endif	
endfunction r$	

function colorDeciphered(textID as integer,aCompareStr$ as string)
	//makes a portion of the last part of a text red thats equal in length to aCompare
	textStr$=getTextString(textID)
	length=len(textStr$)
	length2=length-len(aCompareStr$)-1
	for i= length to length2 step -1
		SetTextCharColor(textID,i,255,0,0,255)
	next i	 
endfunction	


function makeRandomString(s$ as string,fromAsci as integer, toAsci as integer,n as integer,ammount as integer) 
	//Creates a random string of asci characters in the range fromAsci toAsci with the ammount of n 
    r$=s$
    if n <= ammount //then exitfunction r$
		r$=r$+(chr(random(fromAsci,toAsci)))
		r$=makeRandomString(r$,fromAsci,toAsci,n+1,ammount)	
	endif	
endfunction r$

function reverseString(s$ as string)
	//funstion reverses a strin ie pass "olleh" and get "hello" back
	for i=len(s$) to 1 step -1
		r$=r$+Mid(s$,i,1)
	next i	
endfunction	r$
Posted: 21st Mar 2023 13:04
Thought this was handy to share it dumps a heap of characters as bytecode to a text file
and loads the information into a picture this can then be retrieved individually, each pixel
may represent 4 characters so it could be used as an alternative to loading and storing
large amounts of text. example a 128*128 pixel image could represent 128^4 * 128^4
characters and also a method of passing the text handling to the video card

+ Code Snippet
// Project: colorDatabase 
// Created: 2023-03-21

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "colorDatabase" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

type _map
    r as integer
    g as integer
    b as integer
    a as integer
endtype
global maps as _map[]
SetRawWritePath(GetReadPath())
dumpText("test1.txt")
  
img=loadimage("testImage.png") //used to set up an image for sizing memblocks 
loadText("test1.txt") 
img2=ConvertInfoToPic(img)


ConvertPicToInfo(img2)
spr=CreateSprite(Img2)
SetSpritePosition(spr,0,0)
//i as integer
do
	print(maps.length)
	Print(Chr(maps[random(1,maps.length)].r))
	Print(Chr(maps[random(1,maps.length)].b))
	Print(Chr(maps[random(1,maps.length)].g))
	Print(Chr(maps[random(1,maps.length)].a))
	sync()
   
loop

function dumpText(filename as string)
file = OpenToWrite(filename):count=0
//WriteLine(file,words)
repeat
	WriteByte(file,(random(1,255))) //save characters in byte format
	inc count
until count=1024*1024
closefile(file)
endfunction



function loadText(filename as string) 
file = OpenToRead(filename)
myMap as _map
line        as string
count =1
repeat
	myMap.r = (ReadByte(file)) 
	myMap.g = (ReadByte(file)) 
	myMap.b = (readByte(file))
	myMap.a = (readByte(file))
	maps.insert(myMap)
until fileEof(file)=1
CloseFile(file)
endfunction

function ConvertInfoToPic(img)
    imgMemblock = CreateMemblockFromImage(img)
    deleteImage(img)  
    width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    count=0: myMap as _map
    
    if maps.length>0
    for x=0 to width-1 
        for y =0 to height-1 
			if Count<=maps.length
				myMap=maps[count]
							
				offset = (12+((y * width) + x) * 4) - 4
				SetMemblockInt(imgmemblock,offset,myMap.r)
				SetMemblockInt(imgmemblock,offset+1,myMap.g)
				setMemblockInt(imgmemblock,offset+2,myMap.b)
				SetMemblockInt(imgmemblock,offset+3,myMap.a)
				inc Count
				
			endif	
        next
    next
    endif
    newimg=CreateImageFromMemblock(imgMemblock)
    DeleteMemblock(imgMemblock)
endfunction newImg  

function ConvertPicToInfo(img)
	
	imgMemblock = CreateMemblockFromImage(img)
     
    width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    count=0
    myMap as _map
    for x=0 to width-1 
        for y=0 to height-1 
			offset = (12+((y * width) + x) * 4) - 4
			myMap.r=GetMemblockInt(imgmemblock,offset)
            myMap.g=GetMemblockInt(imgmemblock,offset+1)
            myMap.b=GetMemblockInt(imgmemblock,offset+2)
            myMap.a=GetMemblockInt(imgmemblock,offset+3)
            maps.insert(myMap)
        next
    next
    //deleteImage(img)
    DeleteMemblock(imgMemblock)
endfunction //newImg	

function makeRandomString(s$ as string,fromAsci as integer, toAsci as integer,n as integer,ammount as integer) 
	//Creates a random string of asci characters in the range fromAsci toAsci with the ammount of n 
    r$=s$
    if n <= ammount //then exitfunction r$
		r$=r$+(chr(random(fromAsci,toAsci)))
		r$=makeRandomString(r$,fromAsci,toAsci,n+1,ammount)	
	endif	
endfunction r$

a look up method would have to be used ie you could search for a string between two chr(13) characters and retrieve a line and its position pointer
for example
+ Code Snippet
str as string:str=getStringFromImage(img2,Chr(13),1) //delimetered by character13 and location 1
function getStringFromImage(img as integer,Str as string, num as integer)
	delimeter as integer:newStr as string:count as integer
	imgMemblock = CreateMemblockFromImage(img)
	width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    myMap as _map
    for x=0 to width-1 
        for y=0 to height-1 
			offset = (12+((y * width) + x) * 4) - 4
			myMap.r=GetMemblockInt(imgmemblock,offset)
            myMap.g=GetMemblockInt(imgmemblock,offset+1)
            myMap.b=GetMemblockInt(imgmemblock,offset+2)
            myMap.a=GetMemblockInt(imgmemblock,offset+3)
            
         
            if Chr(myMap.r)=left(str,1) :inc delimeter:inc count :endif
            if Chr(myMap.g)=left(str,1) :inc delimeter:inc count :endif
            if Chr(myMap.b)=left(str,1) :inc delimeter:inc count :endif
            if Chr(myMap.a)=left(str,1) :inc delimeter:inc count :endif
            
            if delimeter>0
				newStr=NewStr+Chr(myMap.r)
				newStr=NewStr+Chr(myMap.g)
				newStr=NewStr+Chr(myMap.b)
				newStr=NewStr+Chr(myMap.a)
			endif	
            
            if delimeter>1 
				if count>=num 
					DeleteMemblock(imgmemblock)
					exitfunction trimString(NewStr,left(str,1))
				endif	
			endif	
        next
    next
    DeleteMemblock(imgMemblock)
endfunction NewStr
Posted: 9th Apr 2023 21:51
With some help from Phaelax the below code was created
+ Code Snippet
// Project: ColorDatabase 
// Created: 2023-04-03
//#constant picWidth 256
//#constant picHeight 256
// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "colorDatabase" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

type _str
	r as String
	g as String
	b as String
	a as String	
endtype

type _map
    r as integer
    g as integer
    b as integer
    a as integer
endtype

global maps as _map[]
SetRawWritePath(GetReadPath())
SetBorderColor(255,0,0)
dumpText("test1.txt",256) //dumps a randomstring of text to a file so as later it can be converted to an image
  
loadText("test1.txt") //loads the previously dumped text to convert to an image
img2=ConvertInfoToPic(256)
saveimage(img2,"testImage.png")

img2=loadimage("testimage.png") // 
ConvertPicToInfo(img2)
//deleteImage(img2)
img2 = loadDumpImage2("test1.txt")

spr=CreateSprite(Img2)
SetSpritePosition(spr,0,0)
SetClearColor( 0,0,0 )
SetSpriteTransparency(spr,0 )

do
	//clearscreen()
	Print("test")
	print(maps.length)
	/*Print(chr(maps[maps.length].r))
	Print(Chr(maps[maps.length].b))
	Print(Chr(maps[random(1,maps.length)].g))
	Print(Chr(maps[random(1,maps.length)].a))
	*/
	//if getpointerPressed()
	x=GetPointerX():y=GetPointerY()
		print(lookupRGBAatXY(x,y))
		print(lookupRGBAatImageXY(img2,x,y))
		//print(getStringFromImage(img2,32,1)) //gets the nth occurence of string from image delimeted by chr 32 sometimes troublesome
	//endif	
	sync()
   
loop
/*
function dumpText(filename as string)
file = OpenToWrite(filename):count=0
ch as string
//WriteLine(file,words)
repeat
	repeat
		ch=chr(random(32,90))
	until isPrintable(ch)	
	WriteByte(file,asc(ch)) //save characters in byte format
	inc count
until count=64*64  //the dimentions of the picture
closefile(file)
endfunction
*/


function loadText(filename as string) 
file = OpenToRead(filename)
myMap as _map
line        as string
count =1
repeat
	myMap.r = (ReadByte(file)) 
	myMap.g = (ReadByte(file)) 
	myMap.b = (readByte(file))
	myMap.a = (readByte(file))
	maps.insert(myMap)
until fileEof(file)=1
CloseFile(file)
endfunction

function ConvertInfoToPic(size)
	
    //imgMemblock = CreateMemblockFromImage(img)
    memsize = size*size*4 + 12
	imgMemblock = CreateMemblock(memsize)
    SetMemblockInt(imgMemblock, 0, size)  // img width
	SetMemblockInt(imgMemblock, 4, size)  // img height
	SetMemblockInt(imgMemblock, 8, 32)    // img depth (must be 32)
    //r=32
    //imgMemblock = CreateMemblock(256*256) 
    //size = 12 +64 *64 *4  `memblock 'size' is summary of image width (integer, 4 bytes), image height (integer, 4 bytes), image depth (integer, 4 bytes) - that is 12 bytes - and raw image data (the number of pixels multiplied by 4 bytes)
	//imgmemblock = createMemblock(size)
    
    
    
    //deleteImage(img)  
    width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    count=0: myMap as _map
     global ww as integer:ww=width
     global hh as integer:hh=height  
    if maps.length>0
    for x=0 to width-1 
        for y =0 to height-1 
			if Count<=maps.length
				myMap=maps[count]
							
				offset = (12+((y * width) + x) * 4) - 4
				SetMemblockbyte(imgmemblock,offset,myMap.r)
				SetMemblockbyte(imgmemblock,offset+1,myMap.g)
				setMemblockbyte(imgmemblock,offset+2,myMap.b)
				SetMemblockbyte(imgmemblock,offset+3,myMap.a)
				inc Count
				
			endif	
        next
    next
    endif
    newimg=CreateImageFromMemblock(imgMemblock)
    DeleteMemblock(imgMemblock)
endfunction newImg  

function ConvertPicToInfo(img)
	
	imgMemblock = CreateMemblockFromImage(img)
	
    //imgMemblock = CreateMemblock(64*64)
     
    width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    count=0
    myMap as _map
    for x=0 to width-1 
        for y=0 to height-1 
			offset = (12+((y * width) + x) * 4) - 4
			myMap.r=GetMemblockbyte(imgmemblock,offset)
            myMap.g=GetMemblockbyte(imgmemblock,offset+1)
            myMap.b=GetMemblockbyte(imgmemblock,offset+2)
            myMap.a=GetMemblockbyte(imgmemblock,offset+3)
            maps.insert(myMap)
        next
    next
    //deleteImage(img)
    DeleteMemblock(imgMemblock)
endfunction //newImg	

function makeRandomString(s$ as string,fromAsci as integer, toAsci as integer,n as integer,ammount as integer) 
	//Creates a random string of asci characters in the range fromAsci toAsci with the ammount of n 
    r$=s$
    if n <= ammount //then exitfunction r$
		r$=r$+(chr(random(fromAsci,toAsci)))
		r$=makeRandomString(r$,fromAsci,toAsci,n+1,ammount)	
	endif	
endfunction r$

//str as string:str=getStringFromImage(img2,Chr(32),1) //delimetered by character13 and location 1
function getStringFromImage(img as integer,dStr as integer, num as integer)
	delimeter as integer:newStr as string:newStr="":count as integer: cStr$=chr(dStr)
	imgMemblock = CreateMemblockFromImage(img)
	width = GetMemblockInt(imgmemblock,0)
    height = GetMemblockInt(imgmemblock,4)
    
    count=0
    myMap as _map:myStr as _str
    for x=0 to width-1 
        for y=0 to height-1 
			offset = (12+((y * width) + x) * 4) - 4
			myMap.r=GetMemblockByte(imgmemblock,offset)
            myMap.g=GetMemblockByte(imgmemblock,offset+1)
            myMap.b=GetMemblockByte(imgmemblock,offset+2)
            myMap.a=GetMemblockByte(imgmemblock,offset+3)
            //maps.insert(myMap)
            myStr.r=chr(myMap.r)
            myStr.g=chr(myMap.g)
            myStr.b=chr(myMap.b)
            myStr.a=chr(myMap.a)
   
                 
            if myStr.r=cStr$ :inc delimeter:inc count :endif
            if myStr.g=cstr$ :inc delimeter:inc count :endif
            if myStr.b=cstr$ :inc delimeter:inc count :endif
            if myStr.a=cstr$ :inc delimeter:inc count :endif
				  
			//print(cStr$)	  
				            
            if delimeter>0
				//print("madeit")
				newStr=NewStr+myStr.r+myStr.g+myStr.b+myStr.a
			endif	
			
			//ClearScreen()
           
           if delimeter>0 
				if count>num
					DeleteMemblock(imgmemblock)
					//newStr=TrimString(newStr,mid(cStr$,2,1))
					exitfunction newStr //_trimString(NewStr)
				endif	
			endif
				
        next	
    next
    //print(r$)
    DeleteMemblock(imgMemblock)
    //newStr=_trimString(NewStr)
    //newStr=TrimString(newStr,cStr$)
endfunction newStr

function _trimString(str as string)
	ch as integer
	for i = 1 to len(str)
		ch=asc(mid(str,i,1))
		if  isPrintable(ch)
			s$=s$+mid(str,i,1)
		endif
	next i	
endfunction	s$

print(lookupRGBAatXY(x,y))
print(lookupRGBAatImageXY(img2,x,y))


function lookupRGBAatXY(x as integer,y as integer)
    
    myString as string
    clearScreen()
    setScissor(X,Y,X+1,Y+1)
    render()
    
    img2 = getImage(x,y,1,1)
     
    rem create memblock
    mem = createMemblockfromImage(img2)
    offset = 12
    rem get memblock data
    r = GetMemblockByte(mem,offset)
    g = getMemblockbyte(mem,offset+1)
    b = getMemblockByte(mem,offset+2)
    a = getMemblockByte(mem,offset+3)
    
    rem tidy up
    deletememblock(mem)
    deleteimage(img2)
    setScissor(0,0,0,0)
    myString =chr(r)+chr(g)+chr(b)+chr(a)
    
endfunction myString

function lookupRGBAatImageXY(image,x as integer,y as integer)
    
    myString as String
     
    rem create memblock
    mem = createMemblockfromImage(image)
    
    //size=getMemblockInt(Mem, 0)  // img width
	width = GetMemblockInt(mem,0)
    height = GetMemblockInt(mem,4)
    if x<0 or y<0 then exitfunction ""
    if x>width-1 or y>height-1 then exitfunction ""
    
    offset = (12+((y * width) + x) * 4) - 4
    rem get memblock data
    r = GetMemblockByte(mem,offset)
    g = getMemblockbyte(mem,offset+1)
    b = getMemblockByte(mem,offset+2)
    a = getMemblockByte(mem,offset+3)
    myString =chr(r)+chr(g)+chr(b)+chr(a)
    rem tidy up
    deletememblock(mem)
    //deleteimage(image)
    
endfunction myString







/*
function isPunctuation(ch1 as integer)
	ch as string:ch=chr(ch1)
    if (ch = "!" or ch = "\" or ch = "#" or ch = "$" or ch = "%" or ch = "&" or ch = "\" or ch = "(" or ch = ")" or ch = "*" or ch = "+" or ch = "," or ch = "-" or ch = "." or ch = "/" or ch = ":" or ch = ";" or ch = "<" or ch = "=" or ch = ">" or ch = "?" or ch = "@" or ch = "[" or ch = "\" or ch = "]" or ch = "^" or ch = "`" or ch = "{" or ch = "|" or ch = '}')
        exitfunction 1
	endif
endfunction 0
*/

function isPunctuation(ch as integer)
	ch1 as string:ch1=str(ch)
    punctuation as string[30] = ["!","\","#","$","%","&","\","(",")","*","+",",","-",".","/",":",";","<","=",">","?","@","[","\","]","^","`","{","|","}"]
    punctuation.sort()

    if punctuation.find(ch1) > -1 or ch=34 or ch=32 then exitfunction 1
	
	//if ch=32 then exitfunction 1
	//if str(ch) = StripString(str(ch), " !\#$%&\()*+-./:;<=>?@[]^`{|}") then exitfunction 1
endfunction 0

function isAlphaNumeric(ch as integer)
    //ch1 as integer
    //ch1=asc(left(ch,1))
    if ch >47 and ch <58 then exitfunction 1  //numbers 0 to 9
    if ch >96 and ch <123 then exitfunction 1 //lowercase letters
	if ch >64 and ch <91 then exitfunction 1  //uppercase letters	
endfunction 0

function isPrintable(ch as integer)
	//ch1 as integer:ch1=asc(ch)
    if (isAlphaNumeric(ch)=1 or isPunctuation(ch)=1)
        exitfunction 1
    endif
endfunction 0


// printable character range: 33 to 126 and 128 to 254
// size: width or height of image (it'll be square)
function dumpText(filename as string, size as integer)
    file = OpenToWrite(filename)
    
    dataSize = size*size*4
    
    // write 12 bytes at start of file, this
    // will simplify loading it later
    writeInteger(file, 0)
    writeInteger(file, 0)
    writeInteger(file, 0)
    
    for i = 1 to dataSize
		repeat 
			ch = random(31,200)
		until isPrintable(ch)
		
        //if ch = 127 then ch = 126 // 127 is delete key
        writeByte(file, ch)
    next i
    
    closeFile(file)
endfunction
    

function loadDumpImage2(filename as string)

    m = createMemblockFromFile(filename)
    
    // calculate size of image. This is why we added 12 empty bytes
    // when writing the file, so the image data would be offset and leave
    // room for the header info
    size = sqrt((getMemblockSize(m)-12) / 4)
    setMemblockInt(m, 0, size)
    setMemblockInt(m, 4, size)
    setMemblockInt(m, 8, 32)
    
    img = createImageFromMemblock(m)
    
    deleteMemblock(m)

endfunction img


Function Bit24to8BitColorConvert(img)
    memblock = CreateMemblockFromImage(img)
    width = GetMemblockInt(memblock, 0)
    height = GetMemblockInt(memblock, 4)
    size = GetMemblockSize(memblock)
        for c = 12 to size - 1 step 4
            ThisR = GetMemblockByte(memblock,c)
            ThisG = GetMemblockByte(memblock,c+1)
            ThisB = GetMemblockByte(memblock,c+2)
                        
			ThisR=(ThisR * 7 / 255) << 5 
			ThisG=(ThisG * 7 / 255) << 2 
			ThisB=(ThisB * 3 / 255)
            
            //ThisC = (ThisR*0.30) + (ThisG*0.59) + (THisB*0.11)
            SetMemblockByte(memblock,c,ThisR)
            SetMemblockByte(memblock,c+1,ThisG)
            SetMemblockByte(memblock,c+2,ThisB)
        next c
    ThisIMG = CreateImageFromMemblock(memblock)
    //SaveImage(ThisIMG,"myimage.png")
    DeleteMemblock(memblock)
EndFunction ThisIMG


what was discovered is that lookupRGBAatXY(x,y) and the lookupRGBAatImageXY(img2,x,y) will return different values
this is due to one grabbing a pixel to convert and the other looking up in the image directly.

The program does take a bit to load first time and once you have done so much can be commented out but i wanted to add
getStringFromImage(img2,32,1) will grab a string similar to trim string between delimetered text but will almost hang the program
if there isnt the string its searching for when its in the main loop hence why its commented out
Posted: 17th Apr 2023 18:55
2D basic outline sprite shader
+ Code Snippet
// Project: 2D OutlineShader 
// Created: 2023-04-18

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "2DoutlineShader" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
image=loadimage("4.png") //any image surrounded by transparency
shader=LoadSpriteShader("outline.ps")
spr=createSprite(image)
SetSpriteShader(spr,shader)


do
SetShaderConstantByName(Shader,"colour",1.0,0.0,1.0,1.0)
    Print( ScreenFPS() )
    Sync()
loop


the ps shader code
+ Code Snippet
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif

const float offset = 1.0 / 128.0;
uniform vec4 colour;  
uniform sampler2D texture0; 
varying mediump vec2 uvVarying;

void main()
{
	vec4 col = texture2D(texture0, uvVarying);
	if (col.a > 0.2)
		gl_FragColor = col;
	else {
		float a = texture2D(texture0, vec2 (uvVarying.x + offset, uvVarying.y)).a +
			texture2D(texture0, vec2(uvVarying.x, uvVarying.y - offset)).a +
			texture2D(texture0, vec2(uvVarying.x - offset, uvVarying.y)).a +
			texture2D(texture0, vec2(uvVarying.x, uvVarying.y + offset)).a;
		if (col.a < 1.0 && a > 0.0)
			gl_FragColor = colour; //vec4(0.8,0.8,0.8,0.8);
		else
			gl_FragColor = col;
	}
}
Posted: 9th May 2023 9:28
A simple dithering effect shader
using modulas to only draw odd pixels

dither.ps
+ Code Snippet
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
varying mediump vec2 uvVarying;
uniform sampler2D texture0;
uniform vec4 pixels;
void main(void)
{

vec2 txc = gl_FragCoord.xy;
vec4 pixel_color = texture2D(texture0, uvVarying).rgba;
if (mod(txc.x, 2) < 1)   
	{
   		gl_FragColor = vec4(pixels.rgb,pixel_color.a);
	}
	else if (mod(txc.y, 2) < 1) 
	{
  		gl_FragColor = vec4(pixels.rgb,pixel_color.a);
	}
 	else
	{     
		gl_FragColor = vec4(pixel_color.rgba);
		
	}
}


to use its just a matter of
+ Code Snippet
spr5=createSprite(image)
sh6=LoadSpriteShader("dither.ps")
SetSpritePosition(spr5,128,128)
SetShaderConstantByName(sh6,"pixels",0,0,0,1) //these can be set to any float value between 0 and 1
SetSpriteShader(spr5,sh6)
Posted: 9th May 2023 14:34
and using the dither and adding a glow effect

ditherwithglow.ps
+ Code Snippet
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
varying mediump vec2 uvVarying;
uniform sampler2D texture0;
uniform vec4 colour; 
uniform vec4 pixels;
const float offset = 1.0 / 128.0;
void main(void)
{

vec2 txc = gl_FragCoord.xy;
vec4 pixel_color = texture2D(texture0, uvVarying).rgba;


if (pixel_color.a > 0.2){
if (mod(txc.x, 2) < 1)   
	{
   		gl_FragColor = vec4(pixels.rgb,pixel_color.a);
	}
	else if (mod(txc.y, 2) < 1) 
	{
  		gl_FragColor = vec4(pixels.rgb,pixel_color.a);
	}
 	else
	{     
		gl_FragColor = vec4(pixel_color.rgba);
		
	}
}else
{
	float a = texture2D(texture0, vec2 (uvVarying.x + offset, uvVarying.y)).a +
			texture2D(texture0, vec2(uvVarying.x, uvVarying.y - offset)).a +
			texture2D(texture0, vec2(uvVarying.x - offset, uvVarying.y)).a +
			texture2D(texture0, vec2(uvVarying.x, uvVarying.y + offset)).a;
		if (pixel_color.a < 1.0 && a > 0.0)
			gl_FragColor = vec4(colour); //vec4(0.8,0.8,0.8,0.8);
		else
			gl_FragColor = vec4(pixel_color);
}
}


leaving these two constants to adjust in program
SetShaderConstantByName(shader,"colour",1,0,0,1) ///gives a red glow around edge
SetShaderConstantByName(shader,"pixels",0.76,0.84,0.73,1) //dithered gold effect
Posted: 29th Jul 2023 14:26
HI

I would like to know

why 2 files "ps shader" and "vs shader" are needed to do
a similar affect as DBP only needs one needs one file ?

much thanks to all for creating examples