UIImage: yeniden boyutlandırma, ardından Crop

oy
184

Şimdi tam anlamıyla gün boyunca bu birine yüzümü dayak oldum ve ben doğru vahiy kenarında olduğumu sürekli hissediyorum rağmen, ben sadece benim hedefe ulaşmak mümkün değil.

Ben, iPhone'un kamera veya kütüphaneden bir görüntü kapmak için önemsiz bir mesele olması için bir işlev eşdeğeri kullanılarak, belirli bir yüksekliğe küçültün edeceğini, önümüzdeki benim tasarımın kavramsal aşamalarında zaman, düşünce Dolgu Aspect seçeneği UIImageView (tamamen kodunda), sonra da kapalı kırpmak bir geçti CGRect içinde uymayan bir şey.

kamera veya kütüphaneden orijinal görüntü alma, önemsiz oldu. Diğer iki adım olduğu kanıtlanmıştır kadar zor şok.

Eklenen resim elde etmek çalışıyorum ne olduğunu gösterir. Birisi nezaketinde elimi tutmaya olmak misiniz? Ben bulduk Her kod örneği şu ana kadar görüntü şut baş aşağı olmak bok gibi bakmak, sınırların dışında çizmek veya aksi takdirde sadece düzgün çalışmaz gibi görünüyor.

Oluştur 02/03/2009 saat 21:42
kaynak kullanıcı
Diğer dillerde...                            


16 cevaplar

oy
244

Ben de aynı şeyi gerekli - benim durumumda, bir kez ölçekli uyan bir boyut almak ve sonra genişliğine kalanını sığdırmak için her ucunu kırpmak için. (. Ben manzara çalışıyorum, yani dikey modda eksiklikleri fark etmiş olmayabilir) İşte benim kod - bu UIImage bir categeory parçası. Benim kodunda Hedef boyutu her zaman cihazın tam ekran boyutuna ayarlanır.

@implementation UIImage (Extras)

#pragma mark -
#pragma mark Scale and crop image

- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
    UIImage *sourceImage = self;
    UIImage *newImage = nil;    
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) 
    {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) 
        {
            scaleFactor = widthFactor; // scale to fit height
        }
        else
        {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor)
        {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        }
        else
        {
            if (widthFactor < heightFactor)
            {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
            }
        }
    }   

    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    //pop the context to get back to the default
    UIGraphicsEndImageContext();

    return newImage;
}
Cevap 03/03/2009 saat 07:55
kaynak kullanıcı

oy
77

Yaşlı bir mesaj sizin UIImage yeniden boyutlandırmak için bir yöntem için kod içerir. aşağıdaki gibi ilgili kısmıdır:

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

Bildiğim kadarıyla kırpma konusunda, gidip bir bağlamda için daha ölçekleme için farklı bir boyutu kullanmak yöntemini değiştirmek bile, ortaya çıkan görüntü bağlamında sınırları kırpılır gerektiğine inanıyoruz.

Cevap 02/03/2009 saat 23:32
kaynak kullanıcı

oy
18
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {
    //If scaleFactor is not touched, no scaling will occur      
    CGFloat scaleFactor = 1.0;

    //Deciding which factor to use to scale the image (factor = targetSize / imageSize)
    if (image.size.width > targetSize.width || image.size.height > targetSize.height)
        if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or
            scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.

    UIGraphicsBeginImageContext(targetSize); 

    //Creating the rect where the scaled image is drawn in
    CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2,
                             (targetSize.height -  image.size.height * scaleFactor) / 2,
                             image.size.width * scaleFactor, image.size.height * scaleFactor);

    //Draw the image into the rect
    [image drawInRect:rect];

    //Saving the image, ending image context
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return scaledImage;
}

Ben bunu öneriyorum. Güzel değil mi? ;)

Cevap 23/11/2010 saat 00:09
kaynak kullanıcı

oy
15

Görüntülerin + diğer bazı işlemler yeniden boyutlandırılması ile ilgili bir kod büyük bir parça var. Resimlerinizin boyutunu nasıl ou anlamaya çalışırken ... bu bir geldi http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

Cevap 18/01/2010 saat 15:58
kaynak kullanıcı

oy
7

Hadi bakalım. Bu kimse mükemmel değildir ;-)

DÜZENLEME: comment aşağıya bakınız - ": CGContextSetInterpolationQuality: Belirli görüntülerle Çalışmaz, başarısız olur geçersiz bağlam 0x0 hatası"

// Resizes the image according to the given content mode, taking into account the image's orientation
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode imageToScale:(UIImage*)imageToScale bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality {
    //Get the size we want to scale it to
    CGFloat horizontalRatio = bounds.width / imageToScale.size.width;
    CGFloat verticalRatio = bounds.height / imageToScale.size.height;
    CGFloat ratio;

    switch (contentMode) {
        case UIViewContentModeScaleAspectFill:
            ratio = MAX(horizontalRatio, verticalRatio);
            break;

        case UIViewContentModeScaleAspectFit:
            ratio = MIN(horizontalRatio, verticalRatio);
            break;

        default:
            [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode];
    }

    //...and here it is
    CGSize newSize = CGSizeMake(imageToScale.size.width * ratio, imageToScale.size.height * ratio);


    //start scaling it
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = imageToScale.CGImage;
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                CGImageGetBitmapInfo(imageRef));

    CGContextSetInterpolationQuality(bitmap, quality);

    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, newRect, imageRef);

    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);

    return newImage;
}
Cevap 28/06/2011 saat 19:40
kaynak kullanıcı

oy
6

Bu Swift Jane Satış cevabın bir versiyonudur. Şerefe!

public func resizeImage(image: UIImage, size: CGSize) -> UIImage? {
    var returnImage: UIImage?

    var scaleFactor: CGFloat = 1.0
    var scaledWidth = size.width
    var scaledHeight = size.height
    var thumbnailPoint = CGPointMake(0, 0)

    if !CGSizeEqualToSize(image.size, size) {
        let widthFactor = size.width / image.size.width
        let heightFactor = size.height / image.size.height

        if widthFactor > heightFactor {
            scaleFactor = widthFactor
        } else {
            scaleFactor = heightFactor
        }

        scaledWidth = image.size.width * scaleFactor
        scaledHeight = image.size.height * scaleFactor

        if widthFactor > heightFactor {
            thumbnailPoint.y = (size.height - scaledHeight) * 0.5
        } else if widthFactor < heightFactor {
            thumbnailPoint.x = (size.width - scaledWidth) * 0.5
        }
    }

    UIGraphicsBeginImageContextWithOptions(size, true, 0)

    var thumbnailRect = CGRectZero
    thumbnailRect.origin = thumbnailPoint
    thumbnailRect.size.width = scaledWidth
    thumbnailRect.size.height = scaledHeight

    image.drawInRect(thumbnailRect)
    returnImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return returnImage
}
Cevap 24/12/2015 saat 13:15
kaynak kullanıcı

oy
2

Ben dönüştürülen hızlı Sam Wirch kılavuzuna ve değil çözmek son görüntüde bazı çok hafif "Squishing" var rağmen, benim için iyi çalıştı.

func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage {
    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var offset = CGPointZero
    if image.size.width > image.size.height {
        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.width) - (ratio * image.size.height)
        offset = CGPointMake(delta / 2, 0)
    } else {
        ratio = newSize.width / image.size.height
        delta = (ratio * image.size.height) - (ratio * image.size.width)
        offset = CGPointMake(0, delta / 2)
    }
    let clipRect = CGRectMake(-offset.x, -offset.y, (ratio * image.size.width) + delta, (ratio * image.size.height) + delta)
    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    UIRectClip(clipRect)
    image.drawInRect(clipRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

Herkes objektif c sürümünü istiyorsa, bu onun web sitesinde bulunuyor.

Cevap 16/08/2015 saat 22:00
kaynak kullanıcı

oy
2

Için Xamarin.iOS versiyonu yeniden boyutlandırmak ve ardından UIImage (Aspect Dolgu) kırpmak için nasıl kabul edilen yanıt altındadır

    public static UIImage ScaleAndCropImage(UIImage sourceImage, SizeF targetSize)
    {
        var imageSize = sourceImage.Size;
        UIImage newImage = null;
        var width = imageSize.Width;
        var height = imageSize.Height;
        var targetWidth = targetSize.Width;
        var targetHeight = targetSize.Height;
        var scaleFactor = 0.0f;
        var scaledWidth = targetWidth;
        var scaledHeight = targetHeight;
        var thumbnailPoint = PointF.Empty;
        if (imageSize != targetSize)
        {
            var widthFactor = targetWidth / width;
            var heightFactor = targetHeight / height;
            if (widthFactor > heightFactor)
            {
                scaleFactor = widthFactor;// scale to fit height
            }
            else
            {
                scaleFactor = heightFactor;// scale to fit width
            }
            scaledWidth = width * scaleFactor;
            scaledHeight = height * scaleFactor;
            // center the image
            if (widthFactor > heightFactor)
            {
                thumbnailPoint.Y = (targetHeight - scaledHeight) * 0.5f;
            }
            else
            {
                if (widthFactor < heightFactor)
                {
                    thumbnailPoint.X = (targetWidth - scaledWidth) * 0.5f;
                }
            }
        }
        UIGraphics.BeginImageContextWithOptions(targetSize, false, 0.0f);
        var thumbnailRect = new RectangleF(thumbnailPoint, new SizeF(scaledWidth, scaledHeight));
        sourceImage.Draw(thumbnailRect);
        newImage = UIGraphics.GetImageFromCurrentImageContext();
        if (newImage == null)
        {
            Console.WriteLine("could not scale image");
        }
        //pop the context to get back to the default
        UIGraphics.EndImageContext();

        return newImage;
    }
Cevap 09/09/2014 saat 08:29
kaynak kullanıcı

oy
2

Brad Larson Kodunu güncellenmiştir. Bu yönü verilen rect'in görüntüyü dolduracaktır.

-(UIImage*) scaleAndCropToSize:(CGSize)newSize;
{
    float ratio = self.size.width / self.size.height;

    UIGraphicsBeginImageContext(newSize);

    if (ratio > 1) {
        CGFloat newWidth = ratio * newSize.width;
        CGFloat newHeight = newSize.height;
        CGFloat leftMargin = (newWidth - newHeight) / 2;
        [self drawInRect:CGRectMake(-leftMargin, 0, newWidth, newHeight)];
    }
    else {
        CGFloat newWidth = newSize.width;
        CGFloat newHeight = newSize.height / ratio;
        CGFloat topMargin = (newHeight - newWidth) / 2;
        [self drawInRect:CGRectMake(0, -topMargin, newSize.width, newSize.height/ratio)];
    }

    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}
Cevap 09/01/2012 saat 21:02
kaynak kullanıcı

oy
1

Ben Evgenii Kanvets tarafından gönderildi Swift 3 eşit görüntü ölçek olmadığı saptanmıştır.

İşte görüntüyü ezmek değil işlevin benim Swift 4 sürümü:

static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {

    // This function returns a newImage, based on image
    // - image is scaled uniformaly to fit into a rect of size newSize
    // - if the newSize rect is of a different aspect ratio from the source image
    //     the new image is cropped to be in the center of the source image
    //     (the excess source image is removed)

    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var drawRect = CGRect()

    if newSize.width > newSize.height {

        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.height) - newSize.height
        drawRect = CGRect(x: 0, y: -delta / 2, width: newSize.width, height: newSize.height + delta)

    } else {

        ratio = newSize.height / image.size.height
        delta = (ratio * image.size.width) - newSize.width
        drawRect = CGRect(x: -delta / 2, y: 0, width: newSize.width + delta, height: newSize.height)

    }

    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    image.draw(in: drawRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
} 
Cevap 19/06/2018 saat 00:58
kaynak kullanıcı

oy
1
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0,0.0,ScreenWidth,ScreenHeigth)];
    [scrollView setBackgroundColor:[UIColor blackColor]];
    [scrollView setDelegate:self];
    [scrollView setShowsHorizontalScrollIndicator:NO];
    [scrollView setShowsVerticalScrollIndicator:NO];
    [scrollView setMaximumZoomScale:2.0];
    image=[image scaleToSize:CGSizeMake(ScreenWidth, ScreenHeigth)];
    imageView = [[UIImageView alloc] initWithImage:image];
    UIImageView* imageViewBk = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
    [self.view addSubview:imageViewBk];
    CGRect rect;
    rect.origin.x=0;
    rect.origin.y=0;
    rect.size.width = image.size.width;
    rect.size.height = image.size.height;

    [imageView setFrame:rect];

    [scrollView setContentSize:[imageView frame].size];
    [scrollView setMinimumZoomScale:[scrollView frame].size.width / [imageView frame].size.width];
    [scrollView setZoomScale:[scrollView minimumZoomScale]];
    [scrollView addSubview:imageView];

    [[self view] addSubview:scrollView];

o zaman bu ederek görüntüye ekran görüntüleri alabilir

float zoomScale = 1.0 / [scrollView zoomScale];
CGRect rect;
rect.origin.x = [scrollView contentOffset].x * zoomScale;
rect.origin.y = [scrollView contentOffset].y * zoomScale;
rect.size.width = [scrollView bounds].size.width * zoomScale;
rect.size.height = [scrollView bounds].size.height * zoomScale;

CGImageRef cr = CGImageCreateWithImageInRect([[imageView image] CGImage], rect);

UIImage *cropped = [UIImage imageWithCGImage:cr];

CGImageRelease(cr);
Cevap 23/11/2012 saat 10:31
kaynak kullanıcı

oy
1

Aşağıdaki basit kod benim için çalıştı.

[imageView setContentMode:UIViewContentModeScaleAspectFill];
[imageView setClipsToBounds:YES];
Cevap 27/06/2012 saat 09:07
kaynak kullanıcı

oy
0

İşte bir Swift 3 versiyonu Swift Sam Wirch rehberi William T. tarafından gönderildi

extension UIImage {

    static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {
        var ratio: CGFloat = 0
        var delta: CGFloat = 0
        var offset = CGPoint.zero

        if image.size.width > image.size.height {
            ratio = newSize.width / image.size.width
            delta = (ratio * image.size.width) - (ratio * image.size.height)
            offset = CGPoint(x: delta / 2, y: 0)
        } else {
            ratio = newSize.width / image.size.height
            delta = (ratio * image.size.height) - (ratio * image.size.width)
            offset = CGPoint(x: 0, y: delta / 2)
        }

        let clipRect = CGRect(x: -offset.x, y: -offset.y, width: (ratio * image.size.width) + delta, height: (ratio * image.size.height) + delta)
        UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
        UIRectClip(clipRect)
        image.draw(in: clipRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }

}
Cevap 04/09/2017 saat 12:38
kaynak kullanıcı

oy
0

Bu soru kalanına geçirildi görünüyor, ama ben daha kolay anlaşılması (ve Swift yazılmış) olabilecek bir çözüm için görevimde, bu geldi (ayrıca gönderilen: ? UIImage kırpmak nasıl )


Bir dış sınırlayıcı ölçüde göre bir boyuta bir en-boy oranına göre bölgeye ve ölçek kırpmak için mümkün istedik. İşte benim varyasyonu:

import AVFoundation
import ImageIO

class Image {

    class func crop(image:UIImage, crop source:CGRect, aspect:CGSize, outputExtent:CGSize) -> UIImage {

        let sourceRect = AVMakeRectWithAspectRatioInsideRect(aspect, source)
        let targetRect = AVMakeRectWithAspectRatioInsideRect(aspect, CGRect(origin: CGPointZero, size: outputExtent))

        let opaque = true, deviceScale:CGFloat = 0.0 // use scale of device's main screen
        UIGraphicsBeginImageContextWithOptions(targetRect.size, opaque, deviceScale)

        let scale = max(
            targetRect.size.width / sourceRect.size.width,
            targetRect.size.height / sourceRect.size.height)

        let drawRect = CGRect(origin: -sourceRect.origin * scale, size: image.size * scale)
        image.drawInRect(drawRect)

        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return scaledImage
    }
}

Kafa karıştırıcı bulundu birkaç şey, kırpma ve yeniden boyutlandırma ayrı endişeler bulunmaktadır. Kırpma Eğer drawInRect geçirmek rect'in kökeni ile ele alınır ve ölçekleme boyutu kısmı tarafından ele alınır. Benim durumumda, ben aynı boy oranı benim çıkış rect için, kaynağa kırpma rect'in boyutunu ilişkilendirmek gerekiyordu. ölçek faktörü daha sonra giriş / çıkış, ve bu (drawInRect iletilen) drawRect tatbik edilmesi gerekmektedir.

Bir ihtar bu yaklaşım etkili bir çizdiğiniz imaj görüntü bağlamında daha büyük olduğunu varsayar olmasıdır. Bunu test etmedim, ama / kırpma yakınlaştırma, ancak açıkça yukarıda belirtilen ölçek parametresi olarak ölçek parametresini tanımlayarak işlemek için bu kodu kullanabilirsiniz düşünüyorum. Varsayılan olarak, UIKit ekran çözünürlüğü dayalı bir çarpanı uygular.

Son olarak, bunun UIKit yaklaşım CoreGraphics / Kuvars ve Core Görüntü yaklaşımlara göre daha yüksek seviyede olup görüntü oryantasyon sorunlarını ele almaya görünüyor unutulmamalıdır. Burada bu yazı uyarınca, ayrıca oldukça hızlı ImageIO ikinci olduğunu belirtmekte yarar var: http://nshipster.com/image-resizing/

Cevap 28/05/2015 saat 04:58
kaynak kullanıcı

oy
0

Swift sürümü:

    static func imageWithImage(image:UIImage, newSize:CGSize) ->UIImage {
    UIGraphicsBeginImageContextWithOptions(newSize, true, UIScreen.mainScreen().scale);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))

    let newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return newImage
}
Cevap 24/02/2015 saat 07:32
kaynak kullanıcı

oy
0
- (UIImage*)imageScale:(CGFloat)scaleFactor cropForSize:(CGSize)targetSize
{
    targetSize = !targetSize.width?self.size:targetSize;
    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;

    thumbnailRect.size.width  = targetSize.width*scaleFactor;
    thumbnailRect.size.height = targetSize.height*scaleFactor;
    CGFloat xOffset = (targetSize.width- thumbnailRect.size.width)/2;
    CGFloat yOffset = (targetSize.height- thumbnailRect.size.height)/2;
    thumbnailRect.origin = CGPointMake(xOffset,yOffset);

    [self drawInRect:thumbnailRect];

    UIImage *newImage  = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    UIGraphicsEndImageContext();

    return newImage;
}

işin Örneğin Aşağıda: Sol görüntü - (orijin görüntüsü); Ölçek x2 ile sağ görüntü

Burada görüntü açıklama girin

Görüntüyü ölçeklemek ama çerçevesini (orantıları) devam yöntemini bu şekilde aramak isterseniz:

[yourImage imageScale:2.0f cropForSize:CGSizeZero];
Cevap 12/02/2015 saat 15:30
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more