Here is my version of saving a string or table to an image. This version saves 3 values at a time as rgb. It could save 4, but I found that the alpha value changes the rgb values if it’s less than 255 when I was coding something else. See discussion saveimage() readImage(). The 2 functions, compress and expand, do all the work. The other code is just to create and print strings for examples. The compress function has 2 arguments, image name and string. This function will calculate the width and height image size and the string size as 3 bytes. The 3 byte size is put in the 1st entry of the image and will allow a size of 16,777,215 bytes. The expand function has one argument, image name, and returns the expanded string. This function will get the 3 byte string size from the 1st entry and expand the rest into a table based on the size. The string is created using table.concat. I used a table because that’s faster than constantly re-building a string using (…), string concat. Just to keep thing simple, I’m only printing values from the test string if there are less than 257 bytes. I tried different string sizes and saved 8,000 bytes as a 52x52 image. 80,000 as 164x163. 800,000 as 517x516. 1,000,000 as 578x577. 2,000,000 as 817x816. 3,000,000 as 1001x1000. I stopped at 3,000,000 because the app closed after it created the 1001x1000 image. I don’t know if it crashed because it was creating a 3,000,000 byte table and then the 3,000,000 byte string. Since the string size is saved in the image, you don’t have to keep track of it manually. The program ran in 10 seconds when I used a value of 1,000,000. That was to create a 1,000,000 byte string, convert the bytes and save the image, read the image back, expand the bytes and create a 1,000,000 byte table and then create the 1,000,000 byte string. How big a string can be saved, I don’t know. I guess it’s based on the iPads available memory.
function setup()
tab={}
-- create test string containing the values 0x00 to 0xff.
-- creating a table, then doing a table.concat is faster than
-- doing a string .. (adding to a string).
for z=0,255 do
tab[z+1]=string.char((z)%256) -- keep value in 0-255 range (z>255)
end
inString=table.concat(tab) -- create string from table
print("\
input string size",#inString) --show string size
-- end create test string
compress("Documents:test1",inString) -- compress string and save to an image
outString=expand("Documents:test1") -- read an image and expand to a string
-- print test string if under 257 bytes, don't print larger ones
if #outString <= 256 then
for z=1,#outString do
print(string.format("%02x",string.byte(outString,z)))
end
end
print("\
output string size",#outString) -- show output string size
print("\
end")
-- end print test string
end
function draw()
background(40, 40, 50)
end
function compress(name,strng)
local img1; local count=0
local size=#strng
local x; local y
local v1; local v2; local v3
local a1=256; local a2=256*256
local s1; local s2
-- calculate width by height for image size
x=math.ceil((size+3)/3)
s1=math.ceil(math.sqrt(x))
s2=math.ceil(x/s1)
-- calculate 3 byte string size (b1+b2*256+b3*256*256)
-- max size of 16,777,215 bytes
-- 3 byte size goes in the 1st entry of the image
b1=size; b2=0; b3=0
if b1>=a2 then
b3=math.floor(size/a2)
b1=b1-b3*a2
end
if b1>=a1 then
b2=math.floor(size/a1)
b1=b1-b2*a1
end
img1=image(s1,s2) -- create image area
img1:set(1,1,b1,b2,b3,255) -- put string size in 1st entry
for x=1,s1 do
for y=1,s2 do
if x~=1 or y~=1 then --skip 1st entry, contains size
v1=0;v2=0;v3=0
count = count + 1
if count<=size then
v1=string.byte(strng,count,count)
count = count + 1
if count<=size then
v2=string.byte(strng,count,count)
count = count + 1
if count<=size then
v3=string.byte(strng,count,count)
end
end
img1:set(x,y,v1,v2,v3,255) --save 3 values per set
end
end
end
end
saveImage(name,img1)
end
function expand(name)
local img2=readImage(name)
local tab={}
local str=""
local count=0
local x; local y
local v1; local v2; local v3
local size
v1,v2,v3,aa=img2:get(1,1) -- get string size from 1st entry
size=v1+v2*256+v3*256*256 -- calculate string size
for x=1,img2.width do
for y=1,img2.height do
if x~=1 or y~=1 then -- skip 1st entry, was size
v1,v2,v3,a=img2:get(x,y) -- get 3 values each time
count = count + 1
if count<=size then -- put 3 values in table
tab[count]=string.char(v1)
count = count + 1
if count<=size then
tab[count]=string.char(v2)
count = count + 1
if count<=size then
tab[count]=string.char(v3)
end
end
end
end
end
end
str=table.concat(tab) -- create string from table
return str
end