Page 1 of 1
Choosing where imageData:encode saves
Posted: Tue Dec 09, 2014 9:50 pm
by fmra
Is there a way to do this? I dislike the love.filesystem restrictions, so I use lua io for file placement, but I can't figure out how to control the save location for pictures exported with imageData:encode, or if there is a way to do it.
Is there another way to export png images, a library or method? I'm very close the finishing the program I'm using it in and would rather not have to back edit it all to work with love.filesystem.
Re: Choosing where imageData:encode saves
Posted: Tue Dec 09, 2014 10:10 pm
by davisdude
I hate to be the bearer of bad news, but io. functions are very platform dependent and (typically) have to be coded differently for each OS. That being said, you can use love.filesystem.setIdentity, but that only changes the name of the folder. I'm assuming you're making an image editor of some sort or something. One possible solution is to use
love.system.openURL to open the folder for the user. That way, they can copy and paste the image.
Re: Choosing where imageData:encode saves
Posted: Tue Dec 09, 2014 10:37 pm
by fmra
Not bad news, since I'm not writing it to be mobile or mac, just Windows. As you said, setIdentity only changes the cosmetic name of the folder in %AppData%, so it of no use.
I'm writing a small, very specific, database tool and I'm trying to get it to export generated graphs and charts as PNG images to be used in generated reports or Word.
I'll try using openURL, as that seems like a usable solution. Thank you so much davisdude. =)
Re: Choosing where imageData:encode saves
Posted: Tue Dec 09, 2014 11:37 pm
by davisdude
Well that's good. Glad I helped you.
Re: Choosing where imageData:encode saves
Posted: Wed Dec 10, 2014 3:12 pm
by Positive07
Code: Select all
--save your image as temp.png
--Read the image in the appdata folder
local r = love.filesystem.read("temp.png")
--Open the file where you want to save your image in write-binary mode
local f = io.open("yourimagename.png","wb")
--Write the image to this file
f:write(r)
--Delete the temporary image
love.filesystem.remove("temp.png")
This code takes LOTS of time to execute, imagine:
- Writing an image to the appdata folder
- Reading the file and storing all the information in memory
- Writing lots of content from the memory to a file
And to add to that, the operations happen in the hard disk drive which is WAY slower than RAM
Also images are huge chunks of data, if you dont want to waste memory then you should do something like:
Code: Select all
local size = love.filesystem.getSize("temp.png")
local chsize = 1024 --Chunk size
local iter, endch = math.ceil(size/chsize), size%chsize --Number of iterations and size of the last chunk
local f = io.open("yourimagename.png","w+b")
local temp = love.filesystem.newFile("temp.png","r")
for i = 1, iter do
if i == iter then ch = endch else ch = 1024 end
temp:seek(1024 * (i-1)) --Goto the position we want to read
local data = temp:read(ch) --Read a chunk of data
f:write(data) --Write it to the file
end
--Close all the files and delete the temporary file
temp:close()
f:close()
love.filesystem.remove("temp.png")
This allows you to break the file into chunks and read them, also with this you can monitor the progress and maybe even add a progress bar representing the file being copied.
You could place this in a thread so that it wont stop your game/app.
Still [wiki]love.system.openURL[/wiki] is better but this is just another method
Re: Choosing where imageData:encode saves
Posted: Wed Dec 10, 2014 5:39 pm
by Ref
Hi Positive07!
Tried you image copying suggestion from straight Lua and ran into some problems.
Came up with the following (which works):
Code: Select all
local srcName = '"some image file name"
local srcImage = io.open( srcName, "rb" )
local dstName = "new name for image created"
local dstImage = io.open( dstName, "wb" )
local size = srcImage:seek( 'end' )
local chsize = 1024
local iter = math.floor(size/chsize)
local endch = size%chsize
for i = 1, iter do
if i == iter then ch = endch else ch = 1024 end
srcImage:seek( 'set', 1024 * ( i-1 ) )
local data = srcImage:read( ch )
dstImage:write( data )
print( chsize * i..' bytes read')
end
srcImage:close()
dstImage:close()
Got confused by your use of 'temp' == 'source image' and 'f' == 'new image'.
Wouldn't work unless I changed 'ceil' to' floor' and added 'set' to seek.
Is Love that different?
I usually use the Love file system.
Re: Choosing where imageData:encode saves
Posted: Sat Dec 13, 2014 2:29 am
by Positive07
Ref wrote:Hi Positive07!
...
Got confused by your use of 'temp' == 'source image' and 'f' == 'new image'.
Wouldn't work unless I changed 'ceil' to' floor' and added 'set' to seek.
Is Love that different?
I usually use the Love file system.
It's really probable that my code was wrong, I didnt test it, anyway a pure io implementation doesnt sound like the best idea (finding the source image may get a little bit complicated, also the file path may be protected with admin permissions) but it is possible.
You could replace the filesystem API with [wiki]ImageData:getString[/wiki] and jump the step of reading the file and saving the image to the save directory. But I'm not sure that it works.
If you floor the iterations then you'll miss an iteration, for example if I have a 1.5Kbytes files and I am splitting it in 1Kbytes chunks
If I do 1.5/1 I get 1.5, If I floor the result I get 1.
End chunk will be 0.5, so the foor loop will be
Code: Select all
for i=1,1 do
if i = 1 then ch = 0.5 else ch = 1 end
--Copy the chunk
end
So I will just get 0.5Kbytes copied also if you try to copy more bytes than what exists in the file then there will be no problem, cause it will read as many bytes as it haves available, and if you are at the end then that is 0.
So I think math.ceil is better
Seek works a little bit different from io in comparison to love, there are no "set" or "end" keywords, just a number.
Also when opening a file with io I open it for write/append/binary, so that no info is deleted when writing, I think that behavior is preferred but I'm not sure.