So here’s a very specific piece of code for a very specific situation that most yall will probably never need, but if you do, here it is.
This is pretty much only necessary if you need to open an HEIC image file from the document picker, because in that situation they don’t convert properly into Codea images.
It’s a two-step process.
First it turns an NSURL for the image into a CGImage in the image layer of a UIView. This can be done anywhere in code.
Then it uses UIView’s drawViewHierarchyInRect_afterScreenUpdates_ function to draw that layer to a proper Codea image. This must be called from inside draw() or it will return black.
-- Call from ObjC delegate (any thread).
-- Returns a UIView with the image in its image layer, parked offscreen.
function UIViewFromImageNSURL(oURL)
local data = objc.NSData:dataWithContentsOfURL_(oURL)
local oCIImg = objc.CIImage:imageWithData_(data)
local oExt = oCIImg.extent
local oCGImg = objc.CIContext:context_():createCGImage_fromRect_(oCIImg, oExt)
local nW = oExt.size.width
local nH = oExt.size.height
local nScale = math.min(WIDTH/nW, HEIGHT/nH)
local nOutW = math.floor(nW * nScale)
local nOutH = math.floor(nH * nScale)
local oView = objc.UIView:alloc()
:initWithFrame_(objc.rect(-nOutW, -nOutH, nOutW, nOutH))
oView.layer.contents = oCGImg
oView.layer.contentsGravity = "resize"
objc.viewer.view:addSubview_(oView)
return oView
end
-- MUST be called from draw().
-- Snapshots the view into a Codea image, removes the view, returns the image.
function CodeaImageFromUIViewImageLayer(oView)
local nW = math.floor(oView.frame.size.width)
local nH = math.floor(oView.frame.size.height)
local oImg = objc.UIGraphicsImageRenderer:alloc()
:initWithBounds_(objc.rect(0, 0, nW, nH))
:imageWithActions_(function(oRCtx)
oView:drawViewHierarchyInRect_afterScreenUpdates_(
objc.rect(0, 0, nW, nH), true)
end)
oView:removeFromSuperview_()
return oImg
end
function setup()
viewer.mode = STANDARD
pickedImg = nil
oSnapView = nil
pendingSnap = false
info = "tap to pick"
local Del = objc.delegate("UIDocumentPickerDelegate")
function Del:documentPicker_didPickDocumentsAtURLs_(oPicker, oURLs)
oSnapView = UIViewFromImageNSURL(oURLs[1])
pendingSnap = true
info = "loading..."
end
function Del:documentPickerWasCancelled_(oPicker)
info = "cancelled"
end
del = Del()
end
function draw()
background(40)
if pendingSnap and oSnapView then
pendingSnap = false
pickedImg = CodeaImageFromUIViewImageLayer(oSnapView)
oSnapView = nil
info = pickedImg.width .. "x" .. pickedImg.height
print("result:", tostring(pickedImg), pickedImg.width, pickedImg.height)
end
if pickedImg then
local nS = math.min(WIDTH*0.9/pickedImg.width, HEIGHT*0.7/pickedImg.height)
sprite(pickedImg, WIDTH/2, HEIGHT/2+60, pickedImg.width*nS, pickedImg.height*nS)
end
fill(255); fontSize(16); textAlign(CENTER); textMode(CENTER)
text(info, WIDTH/2, 60)
end
function touched(t)
if t.state ~= BEGAN then return end
local types = {"public.jpeg","public.heic","public.image"}
local doc = objc.UIDocumentPickerViewController
:alloc():initWithDocumentTypes_inMode_(types, 0)
doc.delegate = del
objc.viewer:presentModalViewController_animated_(doc, true)
end
…easy peasy lemon squeezy!
Except actually difficult difficult lemon difficult. ![]()