Beispiel #1
0
 // Create a new image from a file at the given url
 // Returns null if unsuccessful.
 public static ImageInfo IICreateImage(NSURL url)
 {
     ImageInfo ii = new ImageInfo();
     // Try to create an image source to the image passed to us
     IntPtr imageSrc = CGImageSource.CreateWithURL(url, null);
     if (imageSrc != IntPtr.Zero)
     {
         // And if we can, try to obtain the first image available
         IntPtr image = CGImageSource.CreateImageAtIndex(imageSrc, 0, null);
         if (image != IntPtr.Zero)
         {
             // and if we could, create the ImageInfo struct with default values
             ii.fRotation = 0.0f;
             ii.fScaleX = 1.0f;
             ii.fScaleY = 1.0f;
             ii.fTranslateX = 0.0f;
             ii.fTranslateY = 0.0f;
             // the ImageInfo struct owns this CGImageRef now, so no need for a retain.
             ii.fImageRef = image;
             // the ImageInfo struct owns this CFDictionaryRef, so no need for a retain.
             ii.fProperties = CGImageSource.CopyPropertiesAtIndex(imageSrc, 0, null);
             // Setup the orientation transformation matrix so that the image will display with the proper orientation
             IIGetOrientationTransform(ref ii);
         }
         // cleanup the image source
         CFType.CFRelease(imageSrc);
     }
     return ii;
 }
Beispiel #2
0
        // Applies the transformations specified in the ImageInfo struct without drawing the actual image
        public static void IIApplyTransformation(ref ImageInfo image, IntPtr context, CGRect bounds)
        {
            if (context != IntPtr.Zero)
            {
                // Whenever you do multiple CTM changes, you have to be very careful with order.
                // Changing the order of your CTM changes changes the outcome of the drawing operation.
                // For example, if you scale a context by 2.0 along the x-axis, and then translate
                // the context by 10.0 along the x-axis, then you will see your drawing will be
                // in a different position than if you had done the operations in the opposite order.

                // Our intent with this operation is that we want to change the location from which we start drawing
                // (translation), then rotate our axies so that our image appears at an angle (rotation), and finally
                // scale our axies so that our image has a different size (scale).
                // Changing the order of operations will markedly change the results.
                IITranslateContext(ref image, context);
                IIRotateContext(ref image, context, bounds);
                IIScaleContext(ref image, context, bounds);
            }
        }
Beispiel #3
0
        // Draw the image to the given context centered inside the given bounds
        public static void IIDrawImage(ref ImageInfo image, IntPtr context, CGRect bounds)
        {
            CGRect imageRect;

            // Setup the image size so that the image fills it's natural boudaries in the base coordinate system.
            imageRect.size.width = (uint) CGImage.GetWidth(image.fImageRef);
            imageRect.size.height = (uint) CGImage.GetHeight(image.fImageRef);

            // Determine the correct origin of the image such that it is centered in the coordinate system.
            // The exact calculations depends on the image orientation, but the basic idea
            // is that the image is located such that it is positioned so that half the difference
            // between the image's size and the bounds to be drawn is used as it's x/y location.
            if ((image.fProperties == null) || (IIGetImageOrientation(ref image) < 5))
            {
                // For orientations 1-4, the images are unrotated, so the width and height of the base image
                // can be used as the width and height of the coordinate translation calculation.
                imageRect.origin.x = (float) Math.Floor((bounds.size.width - imageRect.size.width)/2.0f);
                imageRect.origin.y = (float) Math.Floor((bounds.size.height - imageRect.size.height)/2.0f);
            }
            else
            {
                // For orientations 5-8, the images are rotated 90 or -90 degrees, so we need to use
                // the image width in place of the height and vice versa.
                imageRect.origin.x = (float) Math.Floor((bounds.size.width - imageRect.size.height)/2.0f);
                imageRect.origin.y = (float) Math.Floor((bounds.size.height - imageRect.size.width)/2.0f);
            }

            // Obtain the orientation matrix for this image
            CGAffineTransform ctm = image.fOrientation;

            // Finally, orient the context so that the image draws naturally.
            CGContext.ConcatCTM(context, ctm);

            // And draw the image.
            CGContext.DrawImage(context, imageRect, image.fImageRef);
        }
Beispiel #4
0
 // Translate the context
 public static void IITranslateContext(ref ImageInfo image, IntPtr context)
 {
     // Translation is easy, just translate.
     CGContext.TranslateCTM(context, image.fTranslateX, image.fTranslateY);
 }
Beispiel #5
0
        // Scale the context around the center point of the given bounds
        public static void IIScaleContext(ref ImageInfo image, IntPtr context, CGRect bounds)
        {
            // First we translate the context such that the 0,0 location is at the center of the bounds
            CGContext.TranslateCTM(context, bounds.size.width/2.0f, bounds.size.height/2.0f);

            // Next we scale the context to the size that we want
            CGContext.ScaleCTM(context, image.fScaleX, image.fScaleY);

            // Finally we have to restore the center position
            CGContext.TranslateCTM(context, -bounds.size.width/2.0f, -bounds.size.height/2.0f);
        }
Beispiel #6
0
        // Rotates the context around the center point of the given bounds
        public static void IIRotateContext(ref ImageInfo image, IntPtr context, CGRect bounds)
        {
            // First we translate the context such that the 0,0 location is at the center of the bounds
            CGContext.TranslateCTM(context, bounds.size.width/2.0f, bounds.size.height/2.0f);

            // Then we rotate the context, converting our angle from degrees to radians
            CGContext.RotateCTM(context, image.fRotation*M_PI/180.0f);

            // Finally we have to restore the center position
            CGContext.TranslateCTM(context, -bounds.size.width/2.0f, -bounds.size.height/2.0f);
        }
Beispiel #7
0
 // Release the ImageInfo struct and other associated data
 // you should not refer to the reference after this call
 // This function is null safe.
 public static void IIRelease(ref ImageInfo image)
 {
     CGImage.Release(image.fImageRef);
     image.fProperties.SafeRelease();
 }
Beispiel #8
0
        // Transforms the context based on the orientation of the image.
        // This ensures the image always appears correctly when drawn.
        public static void IIGetOrientationTransform(ref ImageInfo image)
        {
            float w = (uint) CGImage.GetWidth(image.fImageRef);
            float h = (uint) CGImage.GetHeight(image.fImageRef);
            if (image.fProperties != null)
            {
                // The Orientations listed here are mirroed from CGImageProperties.h,
                // listed under the kCGImagePropertyOrientation key.
                switch (IIGetImageOrientation(ref image))
                {
                    case 1:
                        // 1 = 0th row is at the top, and 0th column is on the left.
                        // Orientation Normal
                        image.fOrientation = CGAffineTransform.Make(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
                        break;

                    case 2:
                        // 2 = 0th row is at the top, and 0th column is on the right.
                        // Flip Horizontal
                        image.fOrientation = CGAffineTransform.Make(-1.0f, 0.0f, 0.0f, 1.0f, w, 0.0f);
                        break;

                    case 3:
                        // 3 = 0th row is at the bottom, and 0th column is on the right.
                        // Rotate 180 degrees
                        image.fOrientation = CGAffineTransform.Make(-1.0f, 0.0f, 0.0f, -1.0f, w, h);
                        break;

                    case 4:
                        // 4 = 0th row is at the bottom, and 0th column is on the left.
                        // Flip Vertical
                        image.fOrientation = CGAffineTransform.Make(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, h);
                        break;

                    case 5:
                        // 5 = 0th row is on the left, and 0th column is the top.
                        // Rotate -90 degrees and Flip Vertical
                        image.fOrientation = CGAffineTransform.Make(0.0f, -1.0f, -1.0f, 0.0f, h, w);
                        break;

                    case 6:
                        // 6 = 0th row is on the right, and 0th column is the top.
                        // Rotate 90 degrees
                        image.fOrientation = CGAffineTransform.Make(0.0f, -1.0f, 1.0f, 0.0f, 0.0f, w);
                        break;

                    case 7:
                        // 7 = 0th row is on the right, and 0th column is the bottom.
                        // Rotate 90 degrees and Flip Vertical
                        image.fOrientation = CGAffineTransform.Make(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
                        break;

                    case 8:
                        // 8 = 0th row is on the left, and 0th column is the bottom.
                        // Rotate -90 degrees
                        image.fOrientation = CGAffineTransform.Make(0.0f, 1.0f, -1.0f, 0.0f, h, 0.0f);
                        break;
                }
            }
        }
Beispiel #9
0
 // Gets the orientation of the image from the properties dictionary if available
 // If the kCGImagePropertyOrientation is not available or invalid,
 // then 1, the default orientation, is returned.
 public static int IIGetImageOrientation(ref ImageInfo image)
 {
     int result = 1;
     if (image.fProperties != null)
     {
         Id value = image.fProperties.ValueForKey(CGImageProperties.kCGImagePropertyOrientation);
         if (value != null)
         {
             NSNumber orientation = value.CastTo<NSNumber>();
             if (orientation != null)
             {
                 result = orientation.IntValue;
             }
         }
     }
     return result;
 }
Beispiel #10
0
        // Draw the image to the given context centered inside the given bounds with
        // the transformation info. The CTM of the context is unchanged after this call
        public static void IIDrawImageTransformed(ref ImageInfo image, IntPtr context, CGRect bounds)
        {
            // We save the current graphics state so as to not disrupt it for the caller.
            CGContext.SaveGState(context);

            // Apply the transformation
            IIApplyTransformation(ref image, context, bounds);

            // Draw the image centered in the context
            IIDrawImage(ref image, context, bounds);

            // Restore our original graphics state.
            CGContext.RestoreGState(context);
        }