function M.unlock_wallpaper(level_id)
local entry = M.get_level_entry(level_id)
if not entry then return end
local bytes = sys.load_resource(entry.bg)
if not bytes then return end
local info = png.info(bytes)
local screen_w, screen_h = window.get_size()
local crop_rect = M.compute_center_crop(level_id, screen_w, screen_h, info.width, info.height)
if not crop_rect then return end
local src_buf = png.decode_rgba(bytes)
if not src_buf then return end
local x, y, w, h = crop_rect.x, crop_rect.y, crop_rect.w, crop_rect.h
local src = buffer.get_stream(src_buf, hash("pixels"))
local out_buf = buffer.create(w * h, {
{ name = hash("pixels"), type = buffer.VALUE_TYPE_UINT8, count = 4 }
})
local out = buffer.get_stream(out_buf, hash("pixels"))
local out_i = 1
for row = 0, h - 1 do
local src_row = (y + (h - 1 - row)) * info.width + x
local src_i = src_row * 4 + 1
local copy_bytes = w * 4
for i = 0, copy_bytes - 1 do
out[out_i + i] = src[src_i + i]
end
out_i = out_i + copy_bytes
end
local target_w, target_h = window.get_size()
-- never upscale (only shrink)
if target_w > w then target_w = w end
if target_h > h then target_h = h end
local png_bytes
if target_w ~= w or target_h ~= h then
local src_scaled = buffer.get_stream(out_buf, hash("pixels"))
local scaled_buf = buffer.create(target_w * target_h, {
{ name = hash("pixels"), type = buffer.VALUE_TYPE_UINT8, count = 4 }
})
local dst = buffer.get_stream(scaled_buf, hash("pixels"))
for yy = 0, target_h - 1 do
local sy = math.floor(yy * h / target_h)
for xx = 0, target_w - 1 do
local sx = math.floor(xx * w / target_w)
local si = (sy * w + sx) * 4 + 1
local di = (yy * target_w + xx) * 4 + 1
dst[di] = src_scaled[si]
dst[di + 1] = src_scaled[si + 1]
dst[di + 2] = src_scaled[si + 2]
dst[di + 3] = src_scaled[si + 3]
end
end
local scaled_pixels = buffer.get_bytes(scaled_buf, hash("pixels"))
png_bytes = png.encode_rgb(scaled_pixels, target_w, target_h)
else
local pixels = buffer.get_bytes(out_buf, hash("pixels"))
png_bytes = png.encode_rgb(pixels, w, h)
end
local filename = ("wallpaper_%s.png"):format(level_id)
local path = sys.get_save_file("A Thousand Bees Wallpapers", filename)
local f = io.open(path, "wb")
if not f then return end
f:write(png_bytes)
f:flush()
f:close()
print("WALLPAPER: unlocked ->", path)
end
```
I calculate the centers from the individual images. I do all this to accomodate diff monitor sizes, so I don’t have to add umpteen premade wallpapers (althought taht is the last resort).
The above function is called from a gui.pick_node event. It currently takes 46s to render the PNG image which is 3508×2480px. I use rgb, but used rgba before. No difference in rendering time.