Resizing images, generating Thumbnails.

Hey Everyone, 

I’m fairly new to Corona and Lua, but I’m very impressed what what it’s capable of.

I have been dabbling for the past week, and built a simple application that takes photos and then displays the results in a scrollView widget. I was stoked at how quick I could this together, all thanks to you guys and the support that already exists. 

I have however encountered my first road block. Running on the simulator the camera was only taking images 201px square. When I put it on the device, and the scrollView gets loaded up with captures, the application then takes forever to load, and will eventually crash. I’m guessing that the iphone (4 in this case) is capturing images much higher than 201px, and it’s maxing out texture memory or something.

So what I want to do is process each image as it’s taken, to produce a thumbnail (square, rather than portrait/landscape) to be used in the scrollView, and still have a higher quality one available when one of the tiles in the scrollView is clicked on. I’m also looking at sending this information to a database, and any optimisations here will help.

I have seen techniques like this: (http://forums.coronalabs.com/topic/25955-is-it-possible-to-resize-images-taken-from-mediashowmediacamera-in-an-app-itself/?hl=%2Bresizing+%2Bimages#entry140431), I was wondering if there were more elegant approaches. I’m used to using software like Nuke and Shake for image processing, and resizing is very straight forward. This must be a common problem. Is this the best way, are there any other suggestions out there?

Thanks for reading!

Campbell

Hi Campbell,

How many images are you placing in the ScrollView before the performance becomes sluggish? This might be an issue of texture memory, but it might be another memory leak instead. Can you run the following texture memory check each time you take/save/place a photo and watch how the value is affected?

[lua]

local texmem = display.newText( “0”, 0, 40, native.systemFont, 16 )

local function checkTexMem()

    collectgarbage(“collect”)

    texmem.text = "TEXMEM: "…(system.getInfo(“textureMemoryUsed”)/1048576)

    texmem.x = display.contentCenterX

end

–after a photo is taken and placed into the ScrollView…

checkTexMem()

[/lua]

This should help determine if it’s a texture memory issue or something else.

Regards,

Brent Sorrentino

Wow, thank you Brent for a great answer. Talk about teaching a man to fish … you helped me track down the memory, and gave me some idea about how to get future debugging information from the device. 

Each image I capture on the device seems adds approximately 15 MB to the texture memory, and when I hit 14 images (226MB) the device just hangs. And I’m testing it by closing the app after the 13th image, and starting it again. I haven’t tested taking more than 14 images without a restart, but it’s performance is very sluggish. On the simulator, each image adds a meagre 250kb to the texture memory.

So I’m thinking that it it’s certainly a texture memory issue, as these values have to be unacceptable. 

You can use display.newImageRect to load the images on the screen. It allows you to specify the width and height of the image, which will resize it for the screen.

Hey Tom, I’m using that already, to place the images:

   local tileWidth = math.ceil(screen.stage.width / xTiles)          local tileHeight = tileWidth         local xTileCount = 0         local yTileCount = 0         local imageHandler = {}         local function imageHandler( imageName )             img = display.newImageRect( imageName, system.DocumentsDirectory, tileWidth, tileHeight)             if img ~= nil then                 img:setReferencePoint(display.TopLeftReferencePoint)                 img.x = (tileWidth \* xTileCount)                 img.y = (tileHeight \* yTileCount)                 scrollView:insert(img)             end             return true         end  

tileWidth and tileHight evaluate to 214 pixels. 

Is this what you mean by using display.newImageRect ?

Hi Campbell.

A couple things for you to think through before you go too far down that garden path of easy breezy prototyping…

The images you are capturing from the device camera typically have dimensions like 1284x2048 pixels (very large, usually over 1 MB in memory, typically 2-4 MB texture memory each). However, iphone screens are only in the 640x960 pixel range. So if your images are only going to be displayed on phones, then you’ve got a lot of wasted pixels there. The larger images also take up a LOT more of that precious texture memory.

If you’re ultimately going to be uploading / downloading them, you’ll probably want to refine a system to resize them on the phone before sending them to the server (otherwise the upload will take a long time, and be prone to breaking due to signal problems). There’s other topics / threads that go through the resizing process (I just saw one active a minute ago - display.save() is typically the call used to resize).

As far as thumbnails go, depending on your app, you may want to create TWO images per picture taken to send to your server. An actual thumbnail (100x100 pixels or some small size that fits your UI while the user is browsing), and a full size (downloaded/displayed when the user taps a thumbnail, or other event where your app shows full size images). Having real (small - under 100k bytes) ) thumbnails would make your initial download much faster than waiting for full size (megabyte?) images to all download. It would also drastically reduce the texture memory needed to show 10, 20 or more of the images onscreen at once.

Hi Campbell,

How many images are you placing in the ScrollView before the performance becomes sluggish? This might be an issue of texture memory, but it might be another memory leak instead. Can you run the following texture memory check each time you take/save/place a photo and watch how the value is affected?

[lua]

local texmem = display.newText( “0”, 0, 40, native.systemFont, 16 )

local function checkTexMem()

    collectgarbage(“collect”)

    texmem.text = "TEXMEM: "…(system.getInfo(“textureMemoryUsed”)/1048576)

    texmem.x = display.contentCenterX

end

–after a photo is taken and placed into the ScrollView…

checkTexMem()

[/lua]

This should help determine if it’s a texture memory issue or something else.

Regards,

Brent Sorrentino

Wow, thank you Brent for a great answer. Talk about teaching a man to fish … you helped me track down the memory, and gave me some idea about how to get future debugging information from the device. 

Each image I capture on the device seems adds approximately 15 MB to the texture memory, and when I hit 14 images (226MB) the device just hangs. And I’m testing it by closing the app after the 13th image, and starting it again. I haven’t tested taking more than 14 images without a restart, but it’s performance is very sluggish. On the simulator, each image adds a meagre 250kb to the texture memory.

So I’m thinking that it it’s certainly a texture memory issue, as these values have to be unacceptable. 

You can use display.newImageRect to load the images on the screen. It allows you to specify the width and height of the image, which will resize it for the screen.

Hey Tom, I’m using that already, to place the images:

   local tileWidth = math.ceil(screen.stage.width / xTiles)          local tileHeight = tileWidth         local xTileCount = 0         local yTileCount = 0         local imageHandler = {}         local function imageHandler( imageName )             img = display.newImageRect( imageName, system.DocumentsDirectory, tileWidth, tileHeight)             if img ~= nil then                 img:setReferencePoint(display.TopLeftReferencePoint)                 img.x = (tileWidth \* xTileCount)                 img.y = (tileHeight \* yTileCount)                 scrollView:insert(img)             end             return true         end  

tileWidth and tileHight evaluate to 214 pixels. 

Is this what you mean by using display.newImageRect ?

Hi Campbell.

A couple things for you to think through before you go too far down that garden path of easy breezy prototyping…

The images you are capturing from the device camera typically have dimensions like 1284x2048 pixels (very large, usually over 1 MB in memory, typically 2-4 MB texture memory each). However, iphone screens are only in the 640x960 pixel range. So if your images are only going to be displayed on phones, then you’ve got a lot of wasted pixels there. The larger images also take up a LOT more of that precious texture memory.

If you’re ultimately going to be uploading / downloading them, you’ll probably want to refine a system to resize them on the phone before sending them to the server (otherwise the upload will take a long time, and be prone to breaking due to signal problems). There’s other topics / threads that go through the resizing process (I just saw one active a minute ago - display.save() is typically the call used to resize).

As far as thumbnails go, depending on your app, you may want to create TWO images per picture taken to send to your server. An actual thumbnail (100x100 pixels or some small size that fits your UI while the user is browsing), and a full size (downloaded/displayed when the user taps a thumbnail, or other event where your app shows full size images). Having real (small - under 100k bytes) ) thumbnails would make your initial download much faster than waiting for full size (megabyte?) images to all download. It would also drastically reduce the texture memory needed to show 10, 20 or more of the images onscreen at once.

Hi,

I was just reading this thread because I was looking up a way to list some images taken by the camera just like Campbell mentioned. I will be uploading the images to a server but I can’t resize them smaller. The reason is the only way I know to resize the images is to display them on the screen and capture the screen as a new image. I need the images to be bigger than the screen still. So does that mean I still need to upload the whole image? I do this in another app and it takes about 10 - 15 seconds per picture to upload.

Thanks,

Warren

Hi,

I was just reading this thread because I was looking up a way to list some images taken by the camera just like Campbell mentioned. I will be uploading the images to a server but I can’t resize them smaller. The reason is the only way I know to resize the images is to display them on the screen and capture the screen as a new image. I need the images to be bigger than the screen still. So does that mean I still need to upload the whole image? I do this in another app and it takes about 10 - 15 seconds per picture to upload.

Thanks,

Warren