Данные UIImage всегда в ландшафтном режиме - PullRequest
2 голосов
/ 19 января 2011

Кажется, что, когда я делаю снимок с камеры в портретном режиме, UIImage имеет правильное соотношение размера / формата (1536x2048 / 3: 4) и ориентацию (справа), экспортированные в файл (с UIImage.AsPNG().Save()), он всегда выходит в ландшафтном режиме (2048x1536, 4: 3).

Это правда, или я что-то не так делаю? И есть ли обходной путь, например, с ALAssetsLibrary.WriteImageToSavedPhotosAlbum?

Обновление: Первоначально я думал, что это также произошло с UIImage.SaveToPhotosAlbum(), но при ближайшем рассмотрении я понимаю, что UIImage в этом случае был не оригиналом с камеры, а скорее воссозданным ранее AsPNG() сохраненные данные.

Обновите снова: Похоже, что это общая «функция» камеры iPhone, и единственный способ исправить это - вручную повернуть изображение. Я попытался перенести этот код на MT, как показано ниже, но мне кажется, что я изобрел новый способ создания чистых изображений с правильным размером и соотношением сторон. Кто-нибудь может обнаружить ошибку?

public static class ImageUtils
{
    static float DefaultMaxSize = 960;

    public static UIImage ScaleAndRotateImage (UIImage image) {
        return ScaleAndRotateImage(image, DefaultMaxSize);
    }

    public static UIImage ScaleAndRotateImage (UIImage image, float maxSize)
    {
        CGImage imgRef = image.CGImage;

        float width = imgRef.Width;
        float height = imgRef.Height;

        CGAffineTransform transform = CGAffineTransform.MakeIdentity();

        RectangleF bounds = new RectangleF (0, 0, width, height);
        if (width > maxSize || height > maxSize) {
            float ratio = width / height;
            if (ratio > 1) {
                bounds.Width = maxSize;
                bounds.Height = bounds.Width / ratio;
            } else {
                bounds.Height = maxSize;
                bounds.Width = bounds.Height * ratio;
            }
        }

        float scaleRatio = bounds.Width / width;
        SizeF imageSize = new SizeF (imgRef.Width, imgRef.Height);
        float boundHeight;
        UIImageOrientation orient = image.Orientation;
        if (orient == UIImageOrientation.Up) {
            //EXIF = 1
            transform = CGAffineTransform.MakeIdentity();
        } else if (orient == UIImageOrientation.UpMirrored) {
            //EXIF = 2
            transform = CGAffineTransform.MakeTranslation (imageSize.Width, 0);
            transform.Scale (-1.0f, 1.0f);
        } else if (orient == UIImageOrientation.Down) {
            //EXIF = 3
            transform = CGAffineTransform.MakeTranslation (imageSize.Width, imageSize.Height);
            transform.Rotate ((float) Math.PI);
        } else if (orient == UIImageOrientation.DownMirrored) {
            //EXIF = 4
            transform = CGAffineTransform.MakeTranslation (0, imageSize.Height);
            transform.Scale (1.0f, -1.0f);
        } else if (orient == UIImageOrientation.LeftMirrored) {
            //EXIF = 5
            boundHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = boundHeight;
            transform = CGAffineTransform.MakeTranslation (imageSize.Height, imageSize.Width);
            transform.Scale (-1.0f, 1.0f);
            transform.Rotate ((float)(3.0f * Math.PI / 2.0));
        } else if (orient == UIImageOrientation.Left) {
            //EXIF = 6
            boundHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = boundHeight;
            transform = CGAffineTransform.MakeTranslation (0, imageSize.Width);
            transform.Rotate ((float)(3.0f * Math.PI / 2.0));
        } else if (orient == UIImageOrientation.RightMirrored) {
            //EXIF = 7
            boundHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = boundHeight;
            transform = CGAffineTransform.MakeScale (-1.0f, 1.0f);
            transform.Rotate ((float)(Math.PI / 2.0));
        } else if (orient == UIImageOrientation.Right) {
            //EXIF = 8
            boundHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = boundHeight;
            transform = CGAffineTransform.MakeTranslation (imageSize.Height, 0);
            transform.Rotate ((float)(Math.PI / 2.0));
        } else {
            throw new InvalidOperationException ("Invalid image orientation");
        }

        UIGraphics.BeginImageContext(bounds.Size);

        CGContext context = UIGraphics.GetCurrentContext ();

        if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
            context.ScaleCTM (-scaleRatio, scaleRatio);
            context.TranslateCTM (-height, 0f);
        } else {
            context.ScaleCTM (scaleRatio, -scaleRatio);
            context.TranslateCTM (0f, -height);
        }

        context.ConcatCTM(transform);

        context.DrawImage (new RectangleF(0, 0, width, height), imgRef);
        UIImage imageCopy = UIGraphics.GetImageFromCurrentImageContext ();
        UIGraphics.EndImageContext ();

        return imageCopy;
    }
}

Ответы [ 3 ]

3 голосов
/ 18 февраля 2011

Нашел ответ здесь: CGContextDrawImage рисует изображение вверх ногами при прохождении UIImage.CGImage : используйте UIImage.Draw() вместо CGContext.DrawImage().Полученный код:

public static UIImage Rotate(UIImage orig) {
    float w0 = orig.Size.Width;
    float h0 = orig.Size.Height;

    UIGraphics.BeginImageContext(new SizeF(w0, h0));
    orig.Draw(new RectangleF(0, 0, w0, h0));
    UIImage imageCopy = UIGraphics.GetImageFromCurrentImageContext ();
    UIGraphics.EndImageContext ();

    return imageCopy;
}

Это позволяет получить изображение правильного размера, формата изображения и ориентации, но с ориентацией всегда "вверх".

3 голосов
/ 28 марта 2011

Я наконец получил это на работу. Вот суть, которая имеет код:

https://gist.github.com/890460

и мой пост в блоге об этом:

http://www.fastchicken.co.nz/2011/03/28/scaling-and-rotating-an-image-in-monotouch/

0 голосов
/ 19 января 2011

Попробуйте преобразовать UIImage в NSData через UIImageJPEGRepresentation, поскольку PNG-изображение не сохраняет значение ориентации вашего изображения.

...