İOS ile bir görüntü boyutu nasıl kolayca yeniden boyutlandırılır / optimize edilir?


114

Uygulamam, ağdan bir dizi görüntü dosyası indiriyor ve bunları yerel iPhone diskine kaydediyor. Bu görüntülerden bazıları oldukça büyük boyuttadır (örneğin, 500 pikselden büyük genişlikler). İPhone'un görüntüyü orijinal boyutunda gösterecek kadar büyük bir ekranı bile olmadığından, alandan / performanstan tasarruf etmek için görüntüyü biraz daha küçük bir boyuta yeniden boyutlandırmayı planlıyorum.

Ayrıca, bu görüntülerden bazıları JPEG'dir ve normal% 60 kalite ayarıyla kaydedilmezler.

İPhone SDK ile bir resmi nasıl yeniden boyutlandırabilirim ve bir JPEG görüntünün kalite ayarını nasıl değiştirebilirim?

Yanıtlar:


246

Bu soruya yanıt olarak birkaç öneri verilmiştir . Bu yazıda açıklanan tekniği ilgili kodla önermiştim :

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

   return newImage;
}

Görüntünün depolanmasıyla ilgili olarak, iPhone ile kullanılacak en hızlı görüntü biçimi PNG'dir, çünkü bu biçim için optimizasyonları vardır. Ancak, bu görüntüleri JPEG olarak saklamak istiyorsanız, UIImage'ınızı alıp aşağıdakileri yapabilirsiniz:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

Bu,% 60 kalite ayarında bir JPEG görüntüsü için ham baytları içeren bir NSData örneği oluşturur. Bu NSData örneğinin içeriği daha sonra diske yazılabilir veya bellekte önbelleğe alınabilir.


1
efendim ... ben de aynı mantığı yazdım ama sağ tarafta bir beyaz düz çizgi görünecek (portre) plz bana çözüm ver
Nag_iphone

1
Merhaba, yeniden boyutlandırırken en boy oranını ve klipleri bağlı tutmakla nasıl başa çıkacağız? Benim durumumda, farklı bir oranı olan bir görüntüyü yeniden boyutlandırdığımda ve ardından "haberleştirdiğimde", deforme olmuş yeniden boyutlandırılmış bir görüntü elde ediyorum. Teşekkürler!
Van Du Tran

1
Bu geçmişte işe yaradı, ancak iOS5.0.1 ve sonraki sürümlerde bu bellek sızıntısına neden oluyor. Bunu başarmanın başka bir yolu var mı?
Usman Nisar

İyileştirilmiş performans için [image drawInRect: rect blendMode: kCGBlendModeCopy alpha: 1.0] kullanmanızı öneririz (bu nedenle, çizim sırasında karıştırma hesaplaması yapmak zorunda değildir
cdemiris99

UIGraphicsBeginImageContextWithOptions (size, NO, 0.0) kullanmalısınız; 0.0, retina ve üzerini desteklemek için ana ekran ölçeğini kullanacaktır. Apple, "Genelde benzer şekilde adlandırılmış UIGraphicsBeginImageContext işlevini çağırmaktan kaçınmalısınız (geriye dönük uyumluluk için bir geri dönüş dışında)" der.
Brad Goss

65

Resimlerinizi yeniden boyutlandırmanın en kolay ve en basit yolu şudur:

float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 320.0/480.0;

if(imgRatio!=maxRatio){
    if(imgRatio < maxRatio){
        imgRatio = 480.0 / actualHeight;
        actualWidth = imgRatio * actualWidth;
        actualHeight = 480.0;
    }
    else{
        imgRatio = 320.0 / actualWidth;
        actualHeight = imgRatio * actualHeight;
        actualWidth = 320.0;
    }
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Bu güzel. Retina ekran çözünürlüğünü korurken (320.0 ve 480.0 değerlerini 640.0 ve 1136.0 olarak değiştirmiş olsam da) bir sunucuya gönderilen görüntüleri yaklaşık 1Mb'den 100k'ye kısaltabildim ve ayrıca ölçeklemeden sonra bir miktar JPEG sıkıştırması yaptım: UIImageJPEGRepresentation (img, 0.7f);
Keller

2
Ya görüntü oranı ve maksimum oran eşit çıkarsa? Örneğin, iamge boyutu 3200x4800 ise?
akshay1188

Bu geçmişte işe yaradı, ancak iOS5.0.1 ve sonraki sürümlerde bu bellek sızıntısına neden oluyor. Bunu başarmanın başka bir yolu var mı?
Usman Nisar

25

Yukarıdaki yöntemler küçük resimler için iyi çalışır, ancak çok büyük bir resmi yeniden boyutlandırmaya çalıştığınızda, hızlı bir şekilde hafızanız biter ve uygulamayı kilitlersiniz. Çok daha iyi bir yol, CGImageSourceCreateThumbnailAtIndexgörüntüyü tamamen kodunu çözmeden yeniden boyutlandırmak için kullanmaktır .

Yeniden boyutlandırmak istediğiniz görüntünün yoluna sahipseniz, bunu kullanabilirsiniz:

- (void)resizeImageAtPath:(NSString *)imagePath {
    // Create the image source (from path)
    CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);

    // To create image source from UIImage, use this
    // NSData* pngData =  UIImagePNGRepresentation(image);
    // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

    // Create thumbnail options
    CFDictionaryRef options = (__bridge CFDictionaryRef) @{
            (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
            (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
            (id) kCGImageSourceThumbnailMaxPixelSize : @(640)
    };
    // Generate the thumbnail
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
    CFRelease(src);
    // Write the thumbnail at path
    CGImageWriteToFile(thumbnail, imagePath);
}

Daha fazla ayrıntı burada .


Teşekkürler, bu çözüm bir cazibe gibi çalışıyor), CGImageSourceResimlere ve pdf'lere ek olarak destekleyen başka dosya formatlarını biliyor musunuz ?
sage444

Teşekkürler. inSampleSizeAndroid'in kod çözücüsü tarafından kullanılan bir analogunu arıyordum . Ve bu, bir görüntüyü hafızayı verimli bir şekilde küçültmenin bir yolunu sağlayan tek cevaptır.
Stan Mots

Bu doğrudan depodaki dosyalarla çalışırken harika sonuçlar aldım, bellek içi görüntülerle de çalışıyor, ancak o kadar hızlı değil (büyük görüntüyü bir UIImage'a yüklemek ve ardından ölçeklendirmek için).
Kendall Helmstetter Gelner

Paylaşım uzantısında çalışmaz. Uygulama hala çok büyük bir görüntüyle çöküyor.
George

18

Görüntü oranını kaybetmeden (yani görüntüyü genişletmeden) görüntüleri ölçeklemenin en iyi yolu şu yöntemi kullanmaktır:

//to scale images without changing aspect ratio
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {

    float width = newSize.width;
    float height = newSize.height;

    UIGraphicsBeginImageContext(newSize);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = image.size.width / width;
    float heightRatio = image.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = image.size.width / divisor;
    height = image.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.origin.y = offset;
    }
    else {
        rect.origin.x = -offset;
    }

    [image drawInRect: rect];

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

    return smallImage;

}

Bu yöntemi Utility sınıfınıza ekleyin, böylece onu projeniz boyunca kullanabilir ve aşağıdaki gibi erişebilirsiniz:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];

Bu yöntem, en-boy oranını korurken ölçeklendirme ile ilgilenir. Ayrıca, küçültülmüş görüntünün genişliği yükseklikten daha fazla olması durumunda (veya tam tersi) görüntüye girintiler ekler.


8

Sunucu üzerinde kontrolünüz varsa, imaj sunucusu tarafını ImageMagik ile yeniden boyutlandırmanızı şiddetle tavsiye ederim . Büyük resimleri indirmek ve bunları telefonda yeniden boyutlandırmak, bant genişliği, pil ve bellek gibi birçok değerli kaynağı boşa harcamaktır. Bunların hepsi telefonlarda kıt.


2
FTFQ: "Uygulamam ağdan bir dizi görüntü dosyası indiriyor"
Rog

Bu alakalı bir cevap olabilir. Soru, görüntülerin ağdan indirildiğini belirtir. OP, görüntü sunucusu tarafında çalışabiliyorsa, yapmalıdır. Yapamazsa, cevap daha çok yardımcı olacaktır.
Joshua Dance

6

Swift'de görüntü ölçekleme için nihai bir çözüm geliştirdim.

Resmi doldurmak için yeniden boyutlandırmak, en boy dolgusu veya belirli boyuta sığdırmak için kullanabilirsiniz.

Görüntüyü ortaya veya dört kenar ve dört köşeden herhangi birine hizalayabilirsiniz.

Ayrıca, orijinal görüntünün en-boy oranları ile hedef boyutunun eşit olmaması durumunda eklenen fazladan alanı kırpabilirsiniz.

enum UIImageAlignment {
    case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
}

enum UIImageScaleMode {
    case Fill,
    AspectFill,
    AspectFit(UIImageAlignment)
}

extension UIImage {
    func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
        let preWidthScale = width.map { $0 / size.width }
        let preHeightScale = height.map { $0 / size.height }
        var widthScale = preWidthScale ?? preHeightScale ?? 1
        var heightScale = preHeightScale ?? widthScale
        switch scaleMode {
        case .AspectFit(_):
            let scale = min(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        case .AspectFill:
            let scale = max(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        default:
            break
        }
        let newWidth = size.width * widthScale
        let newHeight = size.height * heightScale
        let canvasWidth = trim ? newWidth : (width ?? newWidth)
        let canvasHeight = trim ? newHeight : (height ?? newHeight)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)

        var originX: CGFloat = 0
        var originY: CGFloat = 0
        switch scaleMode {
        case .AspectFit(let alignment):
            switch alignment {
            case .Center:
                originX = (canvasWidth - newWidth) / 2
                originY = (canvasHeight - newHeight) / 2
            case .Top:
                originX = (canvasWidth - newWidth) / 2
            case .Left:
                originY = (canvasHeight - newHeight) / 2
            case .Bottom:
                originX = (canvasWidth - newWidth) / 2
                originY = canvasHeight - newHeight
            case .Right:
                originX = canvasWidth - newWidth
                originY = (canvasHeight - newHeight) / 2
            case .TopLeft:
                break
            case .TopRight:
                originX = canvasWidth - newWidth
            case .BottomLeft:
                originY = canvasHeight - newHeight
            case .BottomRight:
                originX = canvasWidth - newWidth
                originY = canvasHeight - newHeight
            }
        default:
            break
        }
        self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Aşağıda bu çözümü uygulamanın örnekleri var.

Gri dikdörtgen, hedef site görüntüsünün yeniden boyutlandırılacağıdır. Açık mavi dikdörtgen içindeki mavi daireler görüntüdür (Çemberler kullandım çünkü ne zaman boyutlarını korumadan ölçeklendiğini görmek kolay). Açık turuncu renk, geçerseniz kırpılacak alanları belirtir trim: true.

Ölçeklemeden önce ve sonra boyut uyumu :

En boy uyumu 1 (önce) En boy uyumu 1 (sonra)

Başka bir görünüm uyumu örneği :

Boyut uyumu 2 (önce) Boyut uyumu 2 (sonra)

Üst hizalamayla en boy uyumu:

Boyut uyumu 3 (öncesi) En boy uyumu 3 (sonra)

En boy dolgusu :

Boyut doldurma (önce) En boy doldurma (sonra)

Doldur :

Doldur (önce) Doldur (sonra)

Örneklerimde ölçek büyütmeyi kullandım çünkü göstermesi daha kolay ancak çözüm aynı zamanda söz konusu olduğu gibi ölçek küçültme için de çalışıyor.

JPEG sıkıştırması için şunu kullanmalısınız:

let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
  // ...
}

Xcode oyun alanı ile benim özüme bakabilirsiniz .


3

Swift 3 için, aşağıdaki kod görüntü oranını koruyarak görüntüyü ölçeklendirir. Apple'ın belgelerinde ImageContext hakkında daha fazla bilgi edinebilirsiniz :

extension UIImage {
    class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
        let scale = newHeight / image.size.height
        let newWidth = image.size.width * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
        image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

Kullanmak için resizeImage()yöntemi çağırın :

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)

2

Bu kodu, görüntüyü gerekli boyutta ölçeklemek için kullanabilirsiniz.

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize
{
    CGSize actSize = image.size;
    float scale = actSize.width/actSize.height;

    if (scale < 1) {
        newSize.height = newSize.width/scale;
    } 
    else {
        newSize.width = newSize.height*scale;
    }

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

    return newImage;
}

2

Bu seansa göre, iOS Memory Deep Dive , ImageIOgörüntüleri küçültmek için daha iyi kullanmıştık .

UIImageKüçültülmüş görüntüler kullanmanın kötü yanı .

  • Orijinal görüntüyü belleğe açacak
  • İç koordinat alanı dönüşümleri pahalıdır

kullanım ImageIO

  • ImageIO, belleği kirletmeden görüntü boyutlarını ve meta veri bilgilerini okuyabilir.

  • ImageIO, görüntüleri yalnızca yeniden boyutlandırılmış görüntü karşılığında yeniden boyutlandırabilir.

Bellekteki Görüntü Hakkında

  • Bellek kullanımı, dosya boyutuyla değil, görüntülerin boyutlarıyla ilgilidir.
  • UIGraphicsBeginImageContextWithOptionsher zaman SRGBpiksel başına 4 bayt kullanan işleme biçimini kullanır .
  • Bir görüntünün load -> decode -> render3 aşaması vardır.
  • UIImage boyutlandırma ve yeniden boyutlandırma için pahalıdır

Aşağıdaki resim için, kullanıyorsanız UIGraphicsBeginImageContextWithOptions , bir resmi yüklemek için yalnızca 590KB'ye ihtiyacımız var 2048 pixels x 1536 pixels x 4 bytes per pixel, kod çözerken = 10MB'ye ihtiyacımız var görüntü açıklamasını buraya girin

UIGraphicsImageRendereriOS 10'da tanıtılan oysa , iOS12'de otomatik olarak en iyi grafik formatını seçecek. Bu, SRGB'ye ihtiyacınız yoksa UIGraphicsBeginImageContextWithOptionsile değiştirerek belleğin% 75'inden tasarruf edebileceğiniz anlamına gelir UIGraphicsImageRenderer.

Bu, bellekteki iOS görüntüleri ile ilgili makalem

func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
    let imgSource = CGImageSourceCreateWithURL(url, nil)
    guard let imageSource = imgSource else {
        return nil
    }

    var scaledImage: CGImage?
    let options: [NSString: Any] = [
            // The maximum width and height in pixels of a thumbnail.
            kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
            kCGImageSourceCreateThumbnailWithTransform: true
    ]
    scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)

    return scaledImage
}


let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")

let url = NSURL(fileURLWithPath: filePath ?? "")

let image = resize(url: url, maxPixelSize: 600)

veya

// Downsampling large images for display at smaller size
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions =
        [kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceShouldCacheImmediately: true,
        // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

1

Retina ekranlarda meydana gelebilecek bir sorun, görüntünün ölçeğinin ImageCapture tarafından ayarlanmasıdır. Yukarıdaki yeniden boyutlandırma işlevleri bunu değiştirmeyecektir. Bu durumlarda yeniden boyutlandırma düzgün çalışmayacaktır.

Aşağıdaki kodda, ölçek 1'e ayarlanmıştır (ölçeklenmemiş) ve döndürülen görüntü beklediğiniz boyuta sahiptir. Bu UIGraphicsBeginImageContextWithOptionsgörüşmede yapılır .

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
    UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
    [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

1

Buradaki bir dizi cevap ekleniyor, ancak boyutlardan ziyade dosya boyutuna göre yeniden boyutlandıran bir çözüm bulmaya gittim.

Bu, verdiğiniz boyuta ulaşana kadar görüntünün hem boyutlarını hem de kalitesini düşürecektir.

func compressTo(toSizeInMB size: Double) -> UIImage? {
    let bytes = size * 1024 * 1024
    let sizeInBytes = Int(bytes)
    var needCompress:Bool = true
    var imgData:Data?
    var compressingValue:CGFloat = 1.0

    while (needCompress) {

        if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) {

            if data.count < sizeInBytes || compressingValue < 0.1 {
                needCompress = false
                imgData = data
            } else {
                compressingValue -= 0.1
            }
        }
    }

    if let data = imgData {
        print("Finished with compression value of: \(compressingValue)")
        return UIImage(data: data)
    }
    return nil
}

private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? {
    let size = CGSize(width: self.size.width*factor, height: self.size.height*factor)
    UIGraphicsBeginImageContext(size)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return newImage;
    }
    return nil
}

Boyut cevabına göre ölçeklendirme için kredi


1

Swift Versiyonu

func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {

    let scale = newWidth / image.size.width
    let newHeight = CGFloat(200.0)
    UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
    image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

0

Eğer herkes için yararlıysa, bir scaleToFitWidthyöntem oluşturmak için Brads tekniğini kullandım UIImage+Extensions...

-(UIImage *)scaleToFitWidth:(CGFloat)width
{
    CGFloat ratio = width / self.size.width;
    CGFloat height = self.size.height * ratio;

    NSLog(@"W:%f H:%f",width,height);

    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

o zaman nerede istersen

#import "UIImage+Extensions.h"

UIImage *newImage = [image scaleToFitWidth:100.0f];

Ayrıca UIView+Extensions, bir UIView'den görüntüler oluşturmak istiyorsanız, bunu bir sınıfa taşıyabileceğinizi de belirtmek gerekir.


0

Cocoa Swift programcıları için bu soruyu cevaplamak istedim. Bu işlev yeni boyutla NSImage döndürür. Bu işlevi şu şekilde kullanabilirsiniz.

        let sizeChangedImage = changeImageSize(image, ratio: 2)






 // changes image size

    func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage   {

    // getting the current image size
    let w = image.size.width
    let h = image.size.height

    // calculating new size
    let w_new = w / ratio 
    let h_new = h / ratio 

    // creating size constant
    let newSize = CGSizeMake(w_new ,h_new)

    //creating rect
    let rect  = NSMakeRect(0, 0, w_new, h_new)

    // creating a image context with new size
    let newImage = NSImage.init(size:newSize)



    newImage.lockFocus()

        // drawing image with new size in context
        image.drawInRect(rect)

    newImage.unlockFocus()


    return newImage

}

0

Resminiz belge dizinindeyse, Bu URL uzantısını ekleyin :

extension URL {
    func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? {
        let imageData = try Data(contentsOf: self)
        debugPrint("Image file size before compression: \(imageData.count) bytes")

        let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg")

        guard let actualImage = UIImage(data: imageData) else { return nil }
        guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else {
            return nil
        }
        debugPrint("Image file size after compression: \(compressedImageData.count) bytes")

        do {
            try compressedImageData.write(to: compressedURL)
            return compressedURL
        } catch {
            return nil
        }
    }
}

Kullanımı:

guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else {
    return
}

//Here you will get URL of compressed image
guard let compressedImageURL = try localImageURL.compressedImageURL() else {
    return
}

debugPrint("compressedImageURL: \(compressedImageURL.absoluteString)")

Not: - <LocalImagePath.jpg> öğesini yerel jpg görüntü yolunuzla değiştirin.


-1

Hala daha iyi bir seçenek arayan biri varsa

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {


    UIImage *sourceImage = image;
    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;
        else
            scaleFactor = heightFactor;

        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;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

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

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

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


    return newImage ;

}

-1
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

Lütfen cevabınızda kodun en azından bazı açıklamalarını sağlayın. Ayrıca okunabilir hale getirmek için cevap düzenleyiciyi kullanarak kodu biçimlendirin.
xpereta

-2

Bir görüntüyü yeniden boyutlandırmak için DrawInRect yerine bu işlevi kullanarak daha iyi (grafiksel) sonuçlar elde ederim:

- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
{
    float lScale = pWidth / pImage.size.width;
    CGImageRef cgImage = pImage.CGImage;
    UIImage   *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
                            orientation:UIImageOrientationRight];
    return lResult;
}

En boy oranına otomatik olarak dikkat edilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.