Taimur Ajmal - 1 year ago 72
Swift Question

# AppleTv / TvOS - Resize TopShelf Images in TVContentItems Saved to ImageURL

I am implementing TopShelf in Apple tvOS. I have downloaded images and assigned to imageURL of TVContentItems. The downloaded images aspect ratio does not fit into the TopShelf Images properly. I have tried to change the size by appending width + height to the image link.

But it didn't work.

Can I do resizing at client end in any other way. In the TVContentItem class I have only have NSURL object. There is no UIImage Object.

Thanks a lot.

Here is Apple's documentation on Image Sizes and shapes

// ~ 2 : 3
// ~ 1 : 1
// ~ 4 : 3
// ~ 16 : 9
// ~ 8 : 3
// ~ 87 : 28

//@property imageShape
//@abstract A TVContentItemImageShape value describing the intended aspect ratio or shape of the image.
//@discussion  For Top Shelf purposes: the subset of values which are //valid in this property, for TVContentItems in the topShelfItems property //of the TVTopShelfProvider, depends on the value of the topShelfStyle //property of the TVTopShelfProvider:

TVTopShelfContentStyleInset:

valid: TVContentItemImageShapeExtraWide

TVTopShelfContentStyleSectioned:

valid: TVContentItemImageShapePoster

valid: TVContentItemImageShapeSquare

valid: TVContentItemImageShapeHDTV


When the value of this property is not valid for the Top Shelf style, the system reserves the right to scale the image in any way.

You're right saying that the TVContentItem has no UIImage type property. Since TVContentItem also accepts local file URLs in the imageURL property, a workaround can be:

• grabbing the UIImage from internet
• creating a new image context with the size of the top shelf image
• saving it into the NSCacheDirectory
• setting the local image URL as imageURL.

Here are the steps:

1. Let's create our TVContentItem object:

let identifier = TVContentIdentifier(identifier: "myPicture", container: wrapperID)!
let contentItem = TVContentItem(contentIdentifier: identifier )!

2. Set the contentItem's imageShape:

contentItem.imageShape = .HDTV

3. Grab the image from Internet. Actually I did this synchronously, you can also try to use other async methods to get that (NSURLConnection, AFNetworking, etc...):

let data : NSData = NSData(contentsOfURL: NSURL(string: "https://s3-ak.buzzfed.com/static/2014-07/16/9/enhanced/webdr08/edit-14118-1405517808-7.jpg")!)!

4. Prepare the path where your image will be saved and get your UIImage from the data object:

let filename = "picture-test.jpg"
let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)
let filepath = paths.first! + "/" + filename
let img : UIImage = UIImage(data: data)!

5. Assuming you've already set the topShelfStyle property, get the size of the top shelf image with the method TVTopShelfImageSizeForShape. This will be the size of your image context:

let shapeSize : CGSize = TVTopShelfImageSizeForShape(contentItem.imageShape, self.topShelfStyle)

6. Create your image context of shapeSize size and draw the downloaded image into the context rect. Here you can do all your modifications to the image to adjust it into the desired size. In this example I took a square image from Instagram and I put white letterbox bands on the right and left sides.

UIGraphicsBeginImageContext(shapeSize)
let imageShapeInRect : CGRect = CGRectMake((shapeSize.width-shapeSize.height)/2,0,shapeSize.height,shapeSize.height)
img.drawInRect(imageShapeInRect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

7. In the end, save this image into your NSCacheDirectory and set the image path as contentItem's imageURL.

UIImageJPEGRepresentation(newImage, 0.8)!.writeToFile(filepath, atomically: true)
contentItem.imageURL = NSURL(fileURLWithPath: filepath)

8. Complete your TVContentItem with other details (like title, internal link, etc...), run the top shelf extension... et voilà!