AppleImage - UBogun/Xojo-iosLib GitHub Wiki

Inherits from AppleObject
Memory leak check: not yet done.
Status: complete

This is an implementation of UIImage, the iOS high-level class for handling and displaying images. iOS uses different kinds of image objects throughout its framework; most of them can be converted via UIImage. Xojo's iOSImage class is basically a UIImage, only you will not find all of its features in the Xojo class.
Please note that like iOSImage AppleImage is an immutable class.

General information

Supported image formats are

Format Filename extensions
TIFF .tiff, .tif
JPEG .jpg, .jpeg
GIF .gif
PNG .png
Windows Bitmap Format (DIB) .bmp, .BMPf
Windows Icon Format .ico
Windows Cursor .cur
X Window System bitmap .xbm

Animated images A UIImage isn’t simply some bitmap information. It’s rather a container class, with AppleCGImage (or AppleCIImage) being the picture itself. As a multi-purpose container, AppleImage can contain several images that can be played in an AppleImageView control, where the duration for the sequence in seconds is passed to one of the AnimatedImagexxx shared methods.

Resizable images
A great way to build custom controls is to use resizable images. They feature the UIEdgeInsets structure to define limits inside the image that will not be scaled – or just in a certain direction – and the core for which several ways to scale it are available.

Example:
Here’s a typical design problem solvable by ResizableImages: I created a button with a slight 3D touch which I’d like to use in an app – take that, flat design! If I would just scale it to different sizes, the corner radii would change or suffer from lower resolution in bigger sizes.
UIEdgeInsets

To avoid this, you can define a UIEdgeInsets structure with top, bottom, left and right insets at positions where the design does not change anymore (whre the fille colors stay the same and the corners are finished. Creating a resizable image from it, the corners will never be scaled, the outer lines only in their respective direction, and the inside will be transformed in two different ways:

  • In one of the ResizableTiledImage methods, the following considerations take place:
  • If resizable areas have a width or height of 1 pixel—that is, a horizontally resizable area is 1 pixel wide, a vertically resizable area is 1 pixel tall, or the center region of the image is 1 x 1 pixel—iOS draws the image by stretching the 1-pixel region. This mode provides the fastest performance (for nonzero cap insets).
  • If resizable areas have a width or height greater than 1 pixel, iOS draws the image by tiling the region. This mode provides reduced performance, but can be useful for images with textured (rather than solid-color) content in their resizable areas.
  • If the entire image is resizable—that is, the capInsets parameter is UIEdgeInsetsZero—and its size is greater than 1 x 1 pixel, iOS draws the image by tiling the entire image. This mode is faster than the tiling mode for nonzero cap insets.
  • And in one of the ResizableStretchedImage methods, the same applies, but the interior will be stretched instead of tiled.

Xojo integration

Currently there's only one method available in iOSImageExtenstion:
AppleImage() As AppleImage which is a shortcut for iOSimage.toAppleImage. Because iOSImage is exactly the same as UIImage and in this case we have a handle, conversion is indeed just swapping the mantles for an instance ptr and very fast.
Finally, it would be best to declare the AppleImage features on the iOSImage handle directly in a module and get rid of handling AppleImage. But that’s a case for future refinements.

Constructors

Constructor (anImage as iOSImage): Creates a new AppleImage from an iOSImage (or rather only takes its handle to allow all features; see above).

Constructor (ImageData as AppleData, opt. Scale As Double): Creates a new AppleImage from image data, optionally interpreting the scale factor supplied. see UIImage Class Reference for supported image formats.

Constructor (anImage AS AppleCGImage, opt. Scale As Double, opt. Orientation As UIImageOrientation = UIImageOrientation.Normal): Creates a new AppleImage from a CGImage, optionally scaled and rotated.

Constructor (anImage AS AppleCIImage, opt. Scale As Double, opt. Orientation As UIImageOrientation = UIImageOrientation.Normal): Creates a new AppleImage from a CIImage, optionally scaled and rotated.

Constructor (ImageName As CFStringRef, opt. bundle as AppleBundle, opt. traitCollection as AppleTraitCollection): Creates an AppleImage from the system image cache or from the app's bundle. You can also search in another bundle by passing an optional bundle. If you don't define a TraitCollection to search an image that belongs to this collection, images belonging the the current screen's collection will be searched. May return NIL. Check the Image's IsNIL property.

Constructor (ImagePath As FolderItem): Creates an AppleImage from the file. This image will not be added to the system image cache. If you only need to use an image in one place in your app, you should use this constructor to lower memory consumption.

Constructors for animated, empty and resizable images as well as images created from code are availalble as shared methods.

Properties

AlignmentRectInsets As UIEdgeInsets (read-only): The alignment rect insets of the image. See SetAlignmentRect

CapInsets As UIEdgeInsets (read-only): The end cap insets. see the ResizableImage shared methods.

CGImage As AppleCGImage (read-only): The CGImage representation of the AppleImage. NIL if the image was created from a CIImage.

CIImage As AppleCIImage (read-only): The CIImage representation of the AppleImage. NIL if the image was created from a CGImage.

Duration As Double (read-only): The time in seconds between two animation images for an animated image.

FlipsInRightToLeftLayout As Boolean (read-only): If true, the image flips automatically in a layout using right to left direction. iOS 9 and above only!

Height As Double (read-only): Convenience property for Size.Height

ImageAsset As AppleImageAsset (read-only): Returns the ImageAsset of the image if it belongs to one. Else NIL. iOS 8 and above only!

ImageOrientation As UIImageOrientation (read-only): Lets you examine image's metadata that may influence the orientation the image is drawn. See UIImageOrientation for examples on what the values mean.

Images As AppleArray of AppleImages (read-only): Returns all animation phase images for an animated image. Else NIL.

PNGData As AppleData (read-only): Returns the image as an AppleData object containing the PNG representation.

RenderingMode As UIImageRenderingMode (read-only): the image's rendering mode. see SetRenderingMode method.

ResizingMode As UIImageResizingMode (read-only): The way the image is scaled if told to do so, namely by tiling or by stretching it.

Scale As Double (read-only): The scale factor of the image.

Size As NSSize (read-only): The size of the image, taking ImageOrientation into account.

toIOSImage As iOSImage (read-only): Converts the image to a Xojo iOSImage.

TraitCollection As AppleTraitCollection (read-only): The trait collection the image belongs to if any. iOS 8 and above only!

Width As Double (read-only): Convenience property for Size.Width

Methods

###Note on draw methods
Please note that all draw methods work on the current AppleCGContext (aka iosGraphics object). You cannot use them for drawing on the screen without a valid current context.

DrawAsPatternInRect (Rect As NSRect): Draws the image as a tiled pattern image in the context's destination rectangle.

DrawAtPoint (Point As NSPoint, opt. BlendMode As CGBlendMode, opt. Alpha As Double = 1): Draws the image at the current context's Point position with optional values for blend mode and alpha.

DrawInRect (Rect As NSRect, opt. BlendMode As CGBlendMode, opt. Alpha As Double = 1): Draws the entire image into the context's destination rect, scaling it as needed. Optional properties as above.


FlipHorizontal() As AppleImage: Returns a copy of the image horizontally flipped (useful if you use right to left layout direction). iOS 9 and above only!

JPEGData (compressionQuality As Double) As AppleData: Returns the image as an AppleData object containing the image's JPEG representation with a compression quality between 0 and 1 or NIL if there was an error.

Resize (XScale As Double, opt. YScale As Double = 0, opt. InterpolationQuality As CGInterpolationQuality = CGInterpolationQuality.Default, opt. Scale As Double = 0) As AppleImage: Returns a new image that is resized with along the x and y axis with the values you provide.
YScale = 0 makes the scale propotional.
Scale = 0 takes the original image's scale property for the scale of the new image.

Resize (NewSize As FoundationFramework.NSSize, opt. proportional As Boolean = False, opt. InterpolationQuality As CGInterpolationQuality = CGInterpolationQuality.Default, opt. Scale As Double = 0) As AppleImage: Returns a new image that is resized to the new size.
Proportional = true makes the image fit proportionally into the size.
Scale = 0 takes the original image's scale property for the scale of the new image.

ResizableStretchedImage (Insets As UICapInsets) As AppleImage: Returns a sizable image from the current image that preserves the size and looks of its borders and corners and only scales the inside of the CapInsets you specify. Its interior will be stretched. This is an ideal method for creating custom button images and similar things.

ResizableTiledImage (Insets As UICapInsets) As AppleImage: Returns a sizable image from the current image that preserves the size and looks of its borders and corners and only scales the inside of the CapInsets you specify. Its interior will be tiled. This is an ideal method for creating custom button images and similar things.

Resize (aRect As NSRect) As AppleImage: Returns a new, proportionally scaled image from the current one that fits into aFrame.

Resize (Factor As Double) As AppleImage: Returns a new, proportionally scaled image from the current one scaled by the factor you define.

SetAlignmentRect (Insets As UICapInsets) As AppleImage: Returns a copy of the current image with the new alignment rect insets. With these, you can fine-tune the positioning of an image. If for example you have a 20 x 20 points sized image with a shine effect of 2 points, you can set the alignment rect to 2,2,16,16 to define the underlying original image.

SetInsets (Insets As UIEdgeInsets) As AppleImage: Returns a new version of the image that uses the specified alignment insets.

SetRenderingMode (RenderingMode As UIImageRenderingMode) As AppleImage: Returns a copy of the image with a selected rendering mode. With this feature it is possible to tell the system to always use the original image or always treat it as a template image.

WriteToPhotoAlbum(): Tries to save the image to the cameraroll or saved photo album. Creates an iOSLibImageDelegate object that will inform the image about the result of the save, raising an event. The delegate object can only inform the image itself as long as it is kept alive as an object. It is probably better to install a custom delegate method somewhere inside a picker controller.
You can override this method to forward a meaningful object (a dictionary maybe) to the receiver of the delegate – it doesn't have to be an AppleImage.

##Shared Methods AnimatedImage (imagename as cfstringref, duration as double) As AppleImage: Creates an animated AppleImage with an interval time of Duration second between the images by loading a sequence of images numbered consecutively from 0 to max. 1024. All images should share the same size and scale. ImageName can be a full path too.

AnimatedImage (Images As AppleArray, duration as double) As AppleImage: Creates an animated AppleImage from an array of UIImages with an interval time of Duration second between the images. All images should share the same size and scale.

AnimatedStretchedResizableImage (imagename as cfstringref, capInsets as UIEdgeInsets, duration as double) As AppleImage: Like the first AnimatedImage method, but creates an animated image with cap insets whose interior will be stretched.

AnimatedTiledResizableImage (imagename as cfstringref, capInsets as UIEdgeInsets, duration as double) As AppleImage: Like the first AnimatedImage method, but creates an animated image with cap insets whose interior will be tiled.

EmptyImage (ASize As Foundationframework.NSSize): Creates an empty image with the specified size.

FromIOSImage (Image As iOSImage) As AppleImage: Convenience method for the constructor (iOSImage).

ImageFromContext (asize as FoundationFrameWork.nssize, paintmethod as ptr, opaque as boolean = false, scale as double = 1) As AppleImage: A Convenience method that enables you to create a custom image from context drawing code. Given a size and the address of a paint method that takes width and height of the Context as Doubles, this method is called with a AppleCGBitmap context prefabricated. You can use context drawing methods and will receive a new image in return. Be aware of possible difficulties with different scale factors!

Example:
This is the draw event handler of an IosLibCanvas:
Dim pic as AppleImage = AppleImage.ImageFromContext (FoundationFrameWork.nsmakesize(300,350), AddressOf contextpaint)
pic.DrawAtPoint FoundationFrameWork.NSMakePoint (20,20)

And this the contextpaint method. It takes Width and height as Doubles as input parameters. They define the height of the current BitMapContext:
dim p as AppleBezierPath = AppleBezierPath.PathWithOval (FoundationFrameWork.NSMakeRect (0,0,Width, height))
AppleColor.GreenColor.SetStrokeAndFill
p.FillWithBlendMode (CoreGraphicsFramework.CGBlendMode.Multiply, 0.6)

This method paints a green oval with 40% transparency that’s multiplied over whatever is already painted on the canvas.

Events

PhotoSaved (context as ptr): Fires when a WriteToPhotoAlbum call was successful. Context can be set in a custom WriteToPhotoAlbum method you'd have to create.

PhotoSaveError (Error As AppleError, Context As Ptr): As above but in case of a save error.

Helper class

iOSLibImageDelegate

is a custom class built on AppleObject that only features one private method:
impl_wroteToPhotoAlbum
which forwards the reply of a WriteToPhotoAlbum method call to the image itself, firing its Photosaved or PhotoSaveError event.
In many cases, you will rather want to implement the method to your view controller. Use it as a template for a custom view controller class.