Posted: 20th Sep 2022 3:02
Hello.
I've been trying to manipulate image file in memblock, and then produce a new image file from said memblock.
But the image file produced can't be read, and had strange size (4.1mb) while the original file is only 53kb.

What I try to do:
- load image
- Create memblock from said image
- Copy each memblock bytes to an array of same size
- Copy bytes from the array to a NEW memblock
- CreateFileFromMemblock to produce a new jpeg image file

Now, I've also created a new image with CreateImageFromMemblock from the NEW memblock, and can texture a sprite with it and display it.
But I just seems to fail to create a new image file from the same NEW memblock.
The resulting file seems to be corrupted or something. It doesn't matter if I create the new image file using CreateImageFromMemblock or the 'traditional' way of openToWrite to a new file, the result is the same. I didn't even modify the memblock.

What did I do wrong?

Here's the example project. Thanks in advance.

+ Code Snippet
// Project: TEST 
// Created: 2022-09-20

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "TEST" )
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


// Create memblock
inputImg = LoadImage("login.jpg")
rawMemblockID = CreateMemblockFromImage( inputImg )
//rawMemblockID = CreateMemblockFromFile("inputImg")
rawMemblockSize# = GetMemblockSize( rawMemblockID )

// Make array to store image data
GLOBAL imgArray AS INTEGER[]
FOR x = 0 TO (rawMemblockSize#-1)
	imgArray.insert( GetMemblockByte(rawMemblockID,x) )
NEXT x


// Make new image memblock
newMemblockID = CreateMemblock( rawMemblockSize# )
FOR x = 0 TO (rawMemblockSize#-1)	
	SetMemblockByte( newMemblockID , x , imgArray[x] )
NEXT x
ImgID = CreateImageFromMemblock( newMemblockID )


//imgID = CreateImageFromMemblock( rawMemblockID )
spriteID = CreateSprite( imgID )
SetSpriteSize( spriteID , GetImageWidth( imgID )*0.5 , GetImageHeight( imgID )*0.5 )

//CreateFileFromMemblock( "raw:" + GetReadPath() + "savefile/" + "test.jpg" , newMemblockID )

//REMSTART
// Make new image file from array
fileID = OpenToWrite( "raw:" + GetReadPath() + "savefile/" + "test.jpg" )
FOR x = 0 TO (rawMemblockSize#-1)
	WriteByte( fileID , imgArray[x] )
NEXt x
CloseFile( fileID )
//REMEND

do
    
	
    Print( GetReadPath() )    
    Sync()
loop
Posted: 20th Sep 2022 4:24
why cast to float?
+ Code Snippet
rawMemblockSize# = GetMemblockSize( rawMemblockID )

why make an array of integers?
+ Code Snippet
GLOBAL imgArray AS INTEGER[]

consider the memblock itself as the array to do whatever you want to the bytes, like convert an image to grayscale:
+ Code Snippet
SetWindowSize( 1280,720, 0 )
SetWindowAllowResize( 1 )

// set display properties
SetVirtualResolution( 1280,720)
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 30, 0 ) 
SetScissor( 0,0,0,0 )
UseNewDefaultFonts( 1 ) 

ThisIMG = LoadImage("mars.png")
GrayIMG = MakeGray(ThisIMG)
OSPR = CreateSprite(ThisIMG)	:	SetSpriteSize(OSPR,640,-1)
GSPR = CreateSprite(GrayIMG)	:	SetSpriteSize(GSPR,640,-1)
SetSpritePosition(GSPR,640,0)

do

    If GetRawKeyState(27) then End    

    Print( ScreenFPS() )
    Sync()
loop


Function MakeGray(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)
			ThisC = (ThisR*0.30) + (ThisG*0.59) + (THisB*0.11)
			SetMemblockByte(memblock,c,ThisC)
			SetMemblockByte(memblock,c+1,ThisC)
			SetMemblockByte(memblock,c+2,ThisC)
		next c
	ThisIMG = CreateImageFromMemblock(memblock)
	SaveImage(ThisIMG,"myimage.png")
	DeleteMemblock(memblock)
	OpenBrowser(GetWritePath()+"/media")
EndFunction ThisIMG



i hope that helps?
Posted: 20th Sep 2022 4:43
@Virtual Nomad

Yeah, the float and array are kinda redundant thing I did just to see if the array can store the info. And it seems it can.
And I can even make a new memblock out of data from the array, and make a new image from that second memblock, and used that image to texture a sprite.

But the problem is, no matter what I did, I just can't create a new image file from the memblock.
I even skipped all the steps, and only try to CreateFileFromMemblock from the freshly-created memblock, basically making a carbon copy of that original file.
My code now literally only have these lines, nothing else, but it still fail to produce a valid image file:

+ Code Snippet
inputImg = LoadImage("login.jpg")
rawMemblockID = CreateMemblockFromImage( inputImg )
CreateFileFromMemblock( "raw:" + GetReadPath() + "savefile/" + "test.jpg" , rawMemblockID )


Any idea why a valid file cannot be produced? Can you reproduce the 'error'?



EDIT: SaveImage() can produce an image file. But CreateFileFromMemblock and WriteByte can't.
Posted: 20th Sep 2022 5:24
i'm pretty sure you're trying to save raw image data in the guise of a compressed jpg = no go.

as i understand it, when the jpg is loaded in, it's automatically converted to (what i call) raw image data and doesn't maintain the jpg compression while you're trying to output that (uncompressed) data as a (compressed) jpg. your image viewer is expecting a jpg format inside (based on the file extension) and it's not there.

something along those lines.
Posted: 20th Sep 2022 5:31
@Virtual Nomad

Ah I see. So there's no way to produce a image file from a memblock in AppGameKit, without compressing it first and churn it out with SaveImage().
Thanks for the clarification. I'll proceed with that in mind.
Posted: 20th Sep 2022 22:28
So there's no way to produce a image file from a memblock in AppGameKit, without compressing it first and churn it out with SaveImage().

I don't think that is true. I have created images using AppGameKit many times


Nice VN. I think that GreyScale converter would be handy in snippets