Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Decreasing size of a photo taken via media.capturePhoto
Started by Allan Hollenberg Apr 07 2014 04:00 AM

9 replies to this topic
media capture photo capture photo size decrease lower
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Allan Hollenberg

[GLOBAL: userInfoPane.html]
Allan Hollenberg
  • Observer

  • 6 posts
  • Enterprise

I've currently got a app in which you need to take a picture and send it off to our server and the client complained about slow sending speed (because of his slow connection but he didn't say that) compared to a different app with roughly the same concept. My only option is to decrease the size of the photo's taken but I can't find this anywhere on Google or in the Corona Documentation..

 

How can I scale down the image to make the file a lot smaller (currently ~7Mb on my iPhone 5)

 



[TOPIC: post.html]
#2

ToeKnee

[GLOBAL: userInfoPane.html]
ToeKnee
  • Contributor

  • 232 posts
  • Corona SDK

+1

Yeah i'd be interested in this as well - would be useful for a future app idea ( when i improve my code ability ).

 

A pertinent question would be 

1) is your photo full screen. So you want to take a full screen photo then scale it!

 

(i don't know if this is actually possible)

or 2) you create a small insert window that shows the camera view - takes photo and result is photo is a smaller size????(than full)

 

i guess it all depends on the type of content that is needed to be photographed - small area or full screen

T.



[TOPIC: post.html]
#3

mpappas

[GLOBAL: userInfoPane.html]
mpappas
  • Contributor

  • 527 posts
  • Enterprise

A typical approach is to do the display.capture, then modify the returned image objects xScale and yScale before the display.save call (passing in the object of course). This will affect the pixel dimensions (and file size) of your final image.

However, it will still produce different dimension images on different devices. Retina devices will produce images approx 4x the dimensions of non-retina, for example.

This is due to display.save saving in the devices native resolution (see display.save docs).  If you want virtually identical pixel dimensions on all devices, then you will also need to factor in display.scaleX/display.scaleY as well.



[TOPIC: post.html]
#4

jonjonsson

[GLOBAL: userInfoPane.html]
jonjonsson
  • Corona Geek

  • 1,051 posts
  • Corona SDK

You can try my function.:

 

 

-- @param photo displayObject Such as a captured image from a camera
-- @param newFileName String Name of new image file in documents directory. Ending in .png or .jpg
-- @param width int The px width of final image in documents directory
-- @param height int The px height of final image in documents directory
local function saveImage(photo, newFileName, width, height)
    
    local endWidth = width * display.contentScaleX
    local endHeight = height * display.contentScaleY
    
    local tempGroup = display.newGroup()
    
    photo.anchorX   = 0.5
    photo.anchorY   = 0.5
    photo.x         = display.contentCenterX
    photo.y         = display.contentCenterY
    tempGroup:insert(photo)
    
    -- Find the bigger scale out of widht or height so it will fill in the crop
    local scale = math.max(endWidth / photo.contentWidth, endHeight / photo.contentHeight)
    photo.width = photo.width * scale
    photo.height = photo.height * scale
    
    -- This object will be used as screen capture boundaries object
    local cropArea   = display.newRect(display.contentCenterX, display.contentCenterY, endWidth, endHeight)
    cropArea.anchorX = 0.5
    cropArea.anchorY = 0.5
    cropArea.x       = display.contentCenterX
    cropArea.y       = display.contentCenterY
    cropArea.alpha   = 0
    tempGroup:insert(cropArea)
    
    -- Now capture the crop area which the user image will be underneith
    local myCaptureImage = display.captureBounds(cropArea.contentBounds)
    
    myCaptureImage.anchorX  = 0.5
    myCaptureImage.anchorY  = 0.5
    myCaptureImage.x        = display.contentCenterX
    myCaptureImage.y        = display.contentCenterY
    
    display.save(myCaptureImage, newFileName) 
    myCaptureImage:removeSelf() -- Remove captured image since we have the image already visible
    myCaptureImage = nil
    
    tempGroup:removeSelf()
    tempGroup = nil
 
end
 
 
local someImage = display.newCircle(200, 200, 150)
saveImage(someImage, "test.jpg", 512, 512)


[TOPIC: post.html]
#5

Allan Hollenberg

[GLOBAL: userInfoPane.html]
Allan Hollenberg
  • Observer

  • 6 posts
  • Enterprise

I thought then when you call display.save it would create a PNG file which is mostly used for flat colors instead of pictures (which need more precise data). If I can just load in the picture, scale it down and save it again as a JPG (without much quality loss due to file the file type) then that would fix my problem. I'll take a look, oh and jonjonsson I'm assuming your code works with any display object right? Not just stuff created by something like display.newCircle or newLine or so.



[TOPIC: post.html]
#6

mpappas

[GLOBAL: userInfoPane.html]
mpappas
  • Contributor

  • 527 posts
  • Enterprise

@allen

I believe if you just use ,jpg for the file extension when calling it, display.save() will save in jpg format.



[TOPIC: post.html]
#7

mpappas

[GLOBAL: userInfoPane.html]
mpappas
  • Contributor

  • 527 posts
  • Enterprise

If you save it as a png, It is pretty lossless in the SDK I believe -- best for photos.  jpg does some heavier compression in the SDK, so much so that on android the filesize is almost a 10-1 ratio.   It's is jpg where they will look worse in Corona -- but much much smaller.

And yes, just changing the extension when you display.save will switch between the formats.



[TOPIC: post.html]
#8

jonjonsson

[GLOBAL: userInfoPane.html]
jonjonsson
  • Corona Geek

  • 1,051 posts
  • Corona SDK

I think the jpg are way too compressed and almost unusable, while the PNG are too big. Really wish we had something in between, configurable would be best and logical.



[TOPIC: post.html]
#9

jonjonsson

[GLOBAL: userInfoPane.html]
jonjonsson
  • Corona Geek

  • 1,051 posts
  • Corona SDK

 jonjonsson I'm assuming your code works with any display object right? Not just stuff created by something like display.newCircle or newLine or so.

 

I use it with images from camera for profile photos as well as game screenshot sharing. 

 

But I'm not in production, so this code has not gotten wide device testing. I sometimes see artifacts in the captured images. Better give it a good testing if you use it.



[TOPIC: post.html]
#10

bill.justice

[GLOBAL: userInfoPane.html]
bill.justice
  • Observer

  • 7 posts
  • Enterprise

 

You can try my function.:

 

 

-- @param photo displayObject Such as a captured image from a camera
-- @param newFileName String Name of new image file in documents directory. Ending in .png or .jpg
-- @param width int The px width of final image in documents directory
-- @param height int The px height of final image in documents directory
local function saveImage(photo, newFileName, width, height)
    
    local endWidth = width * display.contentScaleX
    local endHeight = height * display.contentScaleY
    
    local tempGroup = display.newGroup()
    
    photo.anchorX   = 0.5
    photo.anchorY   = 0.5
    photo.x         = display.contentCenterX
    photo.y         = display.contentCenterY
    tempGroup:insert(photo)
    
    -- Find the bigger scale out of widht or height so it will fill in the crop
    local scale = math.max(endWidth / photo.contentWidth, endHeight / photo.contentHeight)
    photo.width = photo.width * scale
    photo.height = photo.height * scale
    
    -- This object will be used as screen capture boundaries object
    local cropArea   = display.newRect(display.contentCenterX, display.contentCenterY, endWidth, endHeight)
    cropArea.anchorX = 0.5
    cropArea.anchorY = 0.5
    cropArea.x       = display.contentCenterX
    cropArea.y       = display.contentCenterY
    cropArea.alpha   = 0
    tempGroup:insert(cropArea)
    
    -- Now capture the crop area which the user image will be underneith
    local myCaptureImage = display.captureBounds(cropArea.contentBounds)
    
    myCaptureImage.anchorX  = 0.5
    myCaptureImage.anchorY  = 0.5
    myCaptureImage.x        = display.contentCenterX
    myCaptureImage.y        = display.contentCenterY
    
    display.save(myCaptureImage, newFileName) 
    myCaptureImage:removeSelf() -- Remove captured image since we have the image already visible
    myCaptureImage = nil
    
    tempGroup:removeSelf()
    tempGroup = nil
 
end
 
 
local someImage = display.newCircle(200, 200, 150)
saveImage(someImage, "test.jpg", 512, 512)

 




[topic_controls]
 
[/topic_controls]