[Solved!] Resizing screenshots so that they don't make my save files 10MB

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Rhinoceros
Prole
Posts: 35
Joined: Mon Jun 11, 2012 2:59 am
Location: Under the Floorboards

[Solved!] Resizing screenshots so that they don't make my save files 10MB

Post by Rhinoceros »

Hello, I am in the process of making save files for my game, and I want to make preview images for each save on the load screen. Relevant snippets:

save:

Code: Select all

local scrn = love.graphics.newScreenshot() -- gets the image data for a screenshot. This is unfortunate, because everything is drawn as 1080p and scaled down to whatever the resolution is. This means the string this generates is FRIGGIN' HUEG (save files are ~10MB, 1kb of which is actual save info, and the rest is HUEG SCRNSHOT)

local info = {
	scrndata = scrn:getString(), -- gets the string form of the 
	scrnw = scrn:getWidth(), -- width of the screenshot
	scrnh = scrn:getHeight() -- height of the screenshot
	}

info = Tserial.pack(info) -- pack the table to a string

name = "autosave" 

love.filesystem.write("saves/"..name..".rns",info)
The load function doesn't interact with the screenshot at all, but the setup function for the load screen uses this:

Code: Select all

local t = Tserial.unpack(love.filesystem.read("saves/"..v))

graphic = love.image.newImageData(t.scrnw, t.scrnh, t.scrndata)
To reconstruct the image.


The save files are enormous. 10MB save files to save two variables (which is all the game needs for a save/load right now). How can I scale the image data down to a much more reasonable size (1920x1080px -> 425x239px) for use as a thumbnail?

EDIT: I guess I should probably be using :encode() so that the image gets compressed as well, but that didn't occur to me until just now, and I'm not sure if it would work.
Last edited by Rhinoceros on Sat Oct 22, 2016 9:32 pm, edited 1 time in total.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: Resizing screenshots so that they don't make my save files 10MB

Post by Nixola »

That's actually how you're supposed to save image files.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Resizing screenshots so that they don't make my save files 10MB

Post by pgimeno »

If you really need to reduce the size, the only way I can think of is to draw it in resized form to a canvas and use [wiki]Canvas:newImageData[/wiki] to retrieve it.
User avatar
Rhinoceros
Prole
Posts: 35
Joined: Mon Jun 11, 2012 2:59 am
Location: Under the Floorboards

Re: Resizing screenshots so that they don't make my save files 10MB

Post by Rhinoceros »

Ok, yeah, they're compressed now to ~2000kb using :encode("png"). But for some reason, tserial doesn't like to load files with fileData in them. It doesn't return a table when I try to unpack it, and if I try to print the result tserial.unpack passes, it gives me invalid UTF-8 errors.
User avatar
zorg
Party member
Posts: 3468
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Resizing screenshots so that they don't make my save files 10MB

Post by zorg »

Here's how i'd do it:
- Internal canvas size of 1920x1080.
- Create a smaller canvas, like 100x100 or 160x90 or 160x100 or whatever.
- When saving the game, run this function:
- Set active canvas to the small one, and do lg.draw(internalCanvas, 0,0, 0, scalex, scaley) where the two scale params are previewDimensions/internalDimensions... this might mean that the saved screenshot is a frame behind, but that should not pose an issue.
- Get the small canvas' imagedata (Canvas:newImageData), encode that as 'png', receiving a FileData, which you can do :getString on, so you now have a string representation of the PNG image. combine it into your savefile, and it should be small enough.

I dont't think you need to store the preview image size this way.

Edit: I'd say that you could encode your image further into Base64, you wouldn't get UTF-8 decoding errors that way, but the fact is, i haven't found an -encoding- function in löve for that, only that FileData can be created from files having been encoded as base64... which doesn't help here.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
Rhinoceros
Prole
Posts: 35
Joined: Mon Jun 11, 2012 2:59 am
Location: Under the Floorboards

Re: Resizing screenshots so that they don't make my save files 10MB

Post by Rhinoceros »

Does this look right? I've never used canvases for anything before.

Code: Select all

	local scrn = love.graphics.newScreenshot() -- gets the image data for a screenshot

	local canvas = love.graphics.newCanvas(425,239) -- make a canvas that is the proper dimensions
	canvas:renderTo(function()
		love.graphics.setColor(255,255,255) -- set colour to white, i.e. draw normally
		love.graphics.draw(love.graphics.newImage(scrn),0,0, -- draw the screenshot at 0,0
		0, -- 0 rotation
		canvas:getWidth() / love.graphics.getWidth(), -- x scale
		canvas:getHeight() / love.graphics.getHeight() -- y scale
		)
	end)
	
	scrn = canvas:newImageData():encode("png") -- get the image data from the canvas and encode it as a png
Edit: fixed the y scale grabbing width instead of height of the window.

The file size is down to about 140kb now, so that's good.

Tserial is still giving me errors, though, so I might just have to give up on ramming images into save files and just have thumbnails be separate from the actual data.
Last edited by Rhinoceros on Sat Oct 22, 2016 7:45 pm, edited 1 time in total.
User avatar
zorg
Party member
Posts: 3468
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Resizing screenshots so that they don't make my save files 10MB

Post by zorg »

You know, it might be just Tserial being unable to handle arbitrary string data... you could use a better serialization lib, like bitser for example.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
Rhinoceros
Prole
Posts: 35
Joined: Mon Jun 11, 2012 2:59 am
Location: Under the Floorboards

Re: Resizing screenshots so that they don't make my save files 10MB

Post by Rhinoceros »

Well, I'm not understanding bitser at all. do I use it in conjunction with Tserial, or can I put table in it? What functions do I use?
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Resizing screenshots so that they don't make my save files 10MB

Post by s-ol »

Rhinoceros wrote:Well, I'm not understanding bitser at all. do I use it in conjunction with Tserial, or can I put table in it? What functions do I use?
you use bitser.dumps and bitser.loads to save/load tables into strings you can then store where/however you want.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Rhinoceros
Prole
Posts: 35
Joined: Mon Jun 11, 2012 2:59 am
Location: Under the Floorboards

Re: Resizing screenshots so that they don't make my save files 10MB

Post by Rhinoceros »

s-ol wrote: you use bitser.dumps and bitser.loads to save/load tables into strings you can then store where/however you want.
Ahh, ok. I got it to serialize the save data, but if I try to put filedata in the table, it throws an error. How should I go about writing filedata to a file as part of a table?
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], rabbitboots and 9 guests