iOS 8 introduces a UIImageAsset class with a method registerImage:withTraitCollection:. How do I use this class?
Normally, you won't have to. Instead, you'll use an asset catalog. UIImageAsset, in iOS 8, is simply the mechanism underlying image sets in asset catalogs.
For example, in iOS 8, an asset catalog can distinguish between versions of an image intended for different size class situations, using the Width and Height pop-up menus to specify different size class possibilities. Then, when you use an image from an asset catalog in your interface, the right thing happens automatically. If we're on an iPhone with the app rotated to landscape orientation, and if there's both an Any height and a Compact height alternative in the image set, the Compact height version is used. And these features are live; if the app rotates from landscape to portrait, and there's both an Any height and a Compact height alternative in the image set, the Compact height version is replaced with the Any height version in your interface, automatically.
You'll notice that I didn't mention UIImageAsset. However, UIImageAsset is the underlying mechanism. When an image is extracted from an asset catalog through init(named:) and the name of its image set, its imageAsset property is a UIImageAsset. All the images in that image set are available through the UIImageAsset; each image has a trait collection associated with it (its traitCollection), and you can ask the UIImageAsset for the image appropriate to a particular trait collection by calling imageWithTraitCollection:. That, in fact, is exactly what the interface is doing for you. An interface object that can display an image is automatically trait collection–aware in iOS 8; it receives the traitCollectionDidChange: message and responds accordingly.
However, it is also possible to combine images into your own UIImageAsset. In a way, this is like making an asset catalog (or at least an image set) in code! In this example, I'll fetch two images out of the app bundle, and configure them so that one is used when the app is in portrait orientation and the other is used when the app is landscape orientation, automatically:
let tcdisp = UITraitCollection(displayScale: UIScreen.mainScreen().scale)
let tcphone = UITraitCollection(userInterfaceIdiom: .Phone)
let tcreg = UITraitCollection(verticalSizeClass: .Regular)
let tc1 = UITraitCollection(traitsFromCollections: [tcdisp, tcphone, tcreg])
let tccom = UITraitCollection(verticalSizeClass: .Compact)
let tc2 = UITraitCollection(traitsFromCollections: [tcdisp, tcphone, tccom])
let moods = UIImageAsset()
let frowney = UIImage(named:"frowney")
let smiley = UIImage(named:"smiley")
moods.registerImage(frowney, withTraitCollection: tc1)
moods.registerImage(smiley, withTraitCollection: tc2)
After that, if frowney is placed into the interface — for example, by handing it over to a UIImageView as its image, or by assigning it as a UIButton's image — it automatically alternates with smiley when the app changes orientation.
The remarkable thing is that this magic works even though there is no persistent reference to frowney, smiley, or the UIImageAsset (moods). The reason is that frowney and smiley are cached by the system (because of the call to init(named:)), and they each maintain a strong reference to the UIImageAsset with which they are registered.
Related
From Apples documentation I read:
An alternative to creating bitmap images is to use template images or symbol images instead. Template images specify the shape you want to draw, but not the associated color information. Symbol images are similar to template images but are vector based, so they scale to different sizes. Both types of images simplify the process for supporting Dark Mode. They also reduce the number of image assets you must ship with your app.
Do I understand this correct that I can not use a vector based symbol image set as a replacement for bitmap but scalable?
Update
My situation:
I've an Image Set in my iOS project. There I can add three bitmaps for the three scaling options iOS devices support. Those images must be of type *.png
Now I would like to replace those three bitmaps with a single vector graphic file *.svg. This seems not possible. If I want to use vector graphic images I've to add another asset type called "symbol image set" (Xcode -> Editor -> Add Assets -> New Symbol Image Set).
So far so good but now my question. Those "symbol image set" assets only the the shape but not the color information into account. That's why I would like the "old" way where the color information is taken into account but the file being a vector graphics file (*.svg).
You don't actually need a Symbol Set for what you are trying to achieve.
All you need is a vector image in pdf format, marking it as Single Scale
Then, you can mark the asset as template (meaning you can tint it with any color) or original if you want to retain its original colors.
Finally, note that although you supply vector images, Xcode by default will produce png versions for all scales behind the scenes. If you need to preserve the vector data (which can help in some cases where you need to upscale) you can enable Preserve Vector Data as well.
Found new option on xcasset catalogue image property in Xcode 10 called "Auto Scaling".
What does this property do?
Is it in any way related to Resizing: "Preserve Vector Data" when using PDF vector assets?
It looks like this may only be used by WatchOS.
From https://developer.apple.com/documentation/watchkit/supporting_multiple_screen_sizes?language=objc
Alternatively, in watchOS 5 and later, you can provide scalable PDF assets. Add a PDF as a 2x image asset, then set its Auto Scaling attribute to Automatic. When you load the PDF, the system scales the image based on the current device’s screen size as listed in the table. This allows you to provide a single asset for all four screen sizes.
I'm not sure if this works on iOS as well. I was unable to find any mention of auto scaling outside of this WatchKit documentation.
how can I set height and width in scaling and can I depend on the image generated (quality and professional scale generation).
how can I set height and width in scaling
You can't. Specify a maxSize for each scaling.sizes entry and Fine Uploader will proportionally scale the image.
can I depend on the image generated (quality
Quality will be limited if you rely on the browser only. There is an entire section in the documentation that explains how you can generate higher-quality resizes by integrating a third-party resize library. I also discuss why you may or may not want to do this. From the documentation:
Fine Uploader's internal image resize code delegates to the drawImage
method on the browser's native CanvasRenderingContext2D object. This
object is used to manipulate a element, which represents a
submitted image File or Blob. Most browsers use linear interpolation
when resizing images. This can lead to extreme aliasing and moire
patterns which is a deal breaker for anyone resizing images for
art/photo galleries, albums, etc. These kinds of artifacts are
impossible to remove after the fact.
If speed is most important, and precise scaled image generation is not
paramount, you should continue to use Fine Uploader's internal scaling
implementation. However, if you want to generate higher quality scaled
images for upload, you should instead use a third-party library to
resize submitted image files, such as pica or limby-resize. As of
version 5.10 of Fine Uploader, it is extremely easy to integrate such
a plug-in into this library. In fact, Fine Uploader will continue to
properly orient the submitted image file and then pass a properly
sized to the image scaling library of your choice to receive
the resized image file, along with the original full-sized image file
drawn onto a for reference. The only caveat is that, due to
issues with scaling larger images in iOS, you may need to continue to
use Fine Uploader's internal scaling algorithm for that particular OS,
as other third-party scaling libraries most likely do not contain
logic to handle this complex case. Luckily, that is easy to account
for as well.
If you'd like to, for example, use pica to generate higher-quality
scaled images, simply pull pica into your project, and contribute a
scaling.customResizer function, like so:
scaling: {
customResizer: !qq.ios() && function(resizeInfo) {
return new Promise(function(resolve, reject) {
pica.resizeCanvas(resizeInfo.sourceCanvas, resizeInfo.targetCanvas, {}, resolve)
})
},
...
}
i'm planning to build a web app where following feature is used:
Imagine uploading an image,
and the dimensions within the image need to be retrieved
e.g. I would like to know the height and width of the input field.
given the fact I can provide the base image sizes and aspect ratio's.
How would one go about getting the marked dimensions out of the given image?
is there an open API that could do this?
Is this even a possiblity?
The Xcode asset catalogue editor supports an Alignment property for images. It very much seems like this is intended as a mechanism for setting a UIImage's alignmentRectInsets, and Apple's Asset catalogue reference strongly suggests this too:
alignment-insets
Dictionary
The insets for alignmentRectInsets in UIImage or for alignmentRect in NSImage. The inset tag can be omitted.
However, when I load images from a catalogue that I've set an Alignment on with the editor, it don't get an alignment.
I'm loading images using [UIImage imageNamed:].
Is this a known bug, or is there some subtlety I am missing?
I've done some testing and I think I've found why it wasn't working.
There's a (small) Bug
If you don't set all of the alignment values in the asset catalogue editor to something other than 0, then none of the alignment values will be honoured when you load that image resource. As it is perfectly reasonable for some alignment values to be 0, I believe this is a bug and I'll raise it on Radar. However – this said, the feature is still pretty useful and I plan to use it.
Pixels & Points
It's worth knowing that the Alignment, that you set in the asset catalogue editor for a multi-scale PNG, is defined in pixels and not in points.
When you load the asset and then ask the image for its alignmentRectInsets, the result is reported in points. Ie, the scale factor of that particular asset will be applied to the values that you set in the editor.
An example: if you set an alignment of 30, 30, 30, 30 on your #3x asset, then load the UIImage, you'll see it's alignmentRectInsets are 10, 10, 10, 10.
Vector Assets
I also tested a vector asset. Here, you have one vector image, and you specify one set of alignment values for it.
In this case of a single vector asset, the Alignment in the asset catalogue editor is defined in points and not in pixels. This is the opposite situation to a multi-scale PNG!
When you load the asset and ask for its aligmentRectInsets, then you'll see the same values reported, regardless of scale the UIKit loads for that image.
… This actually makes sense, and wouldn't work if done differently. But it seems like it might catch people out.