पहलू अनुपात और चौड़ाई रखकर UIImage का आकार बदलें


136

मैंने पहलू अनुपात रखकर छवि को आकार देने के लिए कई पोस्टों में देखा। ये फ़ंक्शन आकार परिवर्तन करते समय RECT के लिए निश्चित बिंदुओं (चौड़ाई और ऊँचाई) का उपयोग करते हैं। लेकिन मेरी परियोजना में, मुझे केवल चौड़ाई के आधार पर दृश्य का आकार बदलने की आवश्यकता है, ऊंचाई को स्वचालित रूप से पहलू अनुपात के आधार पर लिया जाना चाहिए। किसी ने भी मुझे इसे हासिल करने में मदद की।

जवाबों:


228

श्रीकर की विधि बहुत अच्छी तरह से काम करती है, यदि आप अपने नए आकार की ऊंचाई और चौड़ाई दोनों जानते हैं । यदि आप उदाहरण के लिए केवल उस चौड़ाई को जानते हैं जिसे आप स्केल करना चाहते हैं और ऊँचाई की परवाह नहीं करते हैं, तो आपको पहले ऊँचाई के पैमाने कारक की गणना करनी होगी।

+(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
    float oldWidth = sourceImage.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

22
आपको वास्तव में newWidthयहां चर की आवश्यकता नहीं है , हालांकि यह पहले से ही है i_width
मैथ्यू क्विरोस

2
आपको ऊंचाई से भी विभाजित करने और स्केलिंग कारकों की तुलना करने की आवश्यकता है जो भी 0 के करीब है। ऊपर दिए गए कोड केवल उन छवियों के साथ काम करेंगे जो कि वे उच्च हैं
23

1
यदि मुझे मेरी ऊँचाई का अनुपात भी जानना है और चौड़ाई या ऊँचाई को मापना है, तो मुझे ऊँचाई से भाग देना होगा। लेकिन चूंकि TO से अनुपात और चौड़ाई रखने के लिए स्पष्ट रूप से पूछा गया है, और चौड़ाई या ऊंचाई नहीं है, मेरा उत्तर पूरी तरह से सही है।
Maverick1st

12
शानदार जवाब, धन्यवाद। एक और बात: यदि आप इस विधि का उपयोग करके छवि गुणवत्ता के किसी भी नुकसान का अनुभव करते हैं, तो UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), NO, 0);इसके बजाय उपयोग करेंUIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
Skornos

57

यदि आप यह नहीं जानते हैं कि क्या छवि पोर्ट्रेट या लैंडस्केप होगी (जैसे उपयोगकर्ता कैमरा के साथ तस्वीर लेता है), तो मैंने एक और तरीका बनाया जो अधिकतम चौड़ाई और ऊंचाई के मापदंडों को लेता है।

कहते हैं कि आपके पास UIImage *myLargeImage4: 3 का अनुपात है।

UIImage *myResizedImage = [ImageUtilities imageWithImage:myLargeImage 
                                        scaledToMaxWidth:1024 
                                               maxHeight:1024];

यदि परिदृश्य में आकार संशोधित UIImage 1024x768 होगा; 768x1024 अगर पोर्ट्रेट। यह विधि रेटिना डिस्प्ले के लिए उच्च रेज छवियों को भी उत्पन्न करेगी।

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(size, NO, [[UIScreen mainScreen] scale]);
    } else {
        UIGraphicsBeginImageContext(size);
    }
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();

    return newImage;
}

+ (UIImage *)imageWithImage:(UIImage *)image scaledToMaxWidth:(CGFloat)width maxHeight:(CGFloat)height {
    CGFloat oldWidth = image.size.width;
    CGFloat oldHeight = image.size.height;

    CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

    CGFloat newHeight = oldHeight * scaleFactor;
    CGFloat newWidth = oldWidth * scaleFactor;
    CGSize newSize = CGSizeMake(newWidth, newHeight);

    return [ImageUtilities imageWithImage:image scaledToSize:newSize];
}

1
यह सबसे अच्छी बात है लेकिन यह हमेशा मेरे परिभाषित आकार का दोगुना लौटता है
मशहदी

2
यदि आप केवल डाउनसाइज़िंग चाहते हैं, तो अपसाइज़िंग नहीं, इमेज को शुरू करना न भूलें: इमेज: स्कैडटाउमोक्सवाइट: मैक्सहाइट: विधि: इसके साथ: अगर (छवि.सुझाव। उपलब्धता <चौड़ाई && image.ize.height <height) {वापसी छवि; }
अर्जन

5
अधिकतम चौड़ाई और अधिकतम ऊंचाई के भीतर फिट होने के लिए, आपको स्केल फैक्टर के रूप में न्यूनतम अनुपात की आवश्यकता है min(ratioX, ratioY):। अन्यथा, यदि चौड़ाई बड़ी है, तो यह अधिकतम ऊंचाई पर फिट नहीं हो सकती है।
जेसन स्टर्गेस

ImageUtilities जहां यह है?
टोंग

42

सबसे अच्छा जवाब Maverick 1st का सही ढंग से स्विफ्ट में अनुवाद (नवीनतम स्विफ्ट 3 के साथ काम करना ):

func imageWithImage (sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
    let oldWidth = sourceImage.size.width
    let scaleFactor = scaledToWidth / oldWidth

    let newHeight = sourceImage.size.height * scaleFactor
    let newWidth = oldWidth * scaleFactor

    UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
    sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

38

धन्यवाद @ Maverick1st एल्गोरिथ्म, मैंने इसे लागू किया Swift, मेरे मामले में ऊंचाई इनपुट पैरामीटर है

class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {

    let scale = newHeight / image.size.height
    let newWidth = image.size.width * scale
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

18

यह विधि UIImage पर एक श्रेणी है। AVFoundation का उपयोग करके कोड की कुछ पंक्तियों में फिट होने का पैमाना है। आयात करने के लिए मत भूलना #import <AVFoundation/AVFoundation.h>

@implementation UIImage (Helper)

- (UIImage *)imageScaledToFitToSize:(CGSize)size
{
    CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(self.size, CGRectMake(0, 0, size.width, size.height));
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    [self drawInRect:scaledRect];
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaledImage;
}

@end

2
यह मेरे लिए सबसे छोटी स्मृति पदचिह्न के साथ सर्वोत्तम परिणाम देने के लिए मिला। +1
टॉमी सी।

11

@ जानोस द्वारा जवाब के आधार पर पहलू-फिट-से- ऊँचाई का 5 संस्करण

आधुनिक UIGraphicsImageRendererएपीआई का उपयोग करता है, इसलिए एक वैध UIImageको वापस लौटने की गारंटी है।

extension UIImage
{
    /// Given a required height, returns a (rasterised) copy
    /// of the image, aspect-fitted to that height.

    func aspectFittedToHeight(_ newHeight: CGFloat) -> UIImage
    {
        let scale = newHeight / self.size.height
        let newWidth = self.size.width * scale
        let newSize = CGSize(width: newWidth, height: newHeight)
        let renderer = UIGraphicsImageRenderer(size: newSize)

        return renderer.image { _ in
            self.draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
}

आप इसे (वेक्टर-आधारित) पीडीएफ छवि परिसंपत्ति के साथ संयोजन में उपयोग कर सकते हैं, किसी भी रेंडर आकार में गुणवत्ता को संरक्षित करने के लिए।


7

सबसे सरल तरीका यह है कि अपने फ्रेम को सेट करें UIImageViewऔर contentModeआकार बदलने वाले विकल्पों में से एक को सेट करें।

कोड इस तरह से है - यह एक उपयोगिता विधि के रूप में इस्तेमाल किया जा सकता है -

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

ध्यान रखें कि ओपी ने UIImageView का उल्लेख नहीं किया है। इसके बजाय, वह संभवत: सीधे UIImage [a] की एक कॉपी को पहलू-फिट करना चाहता था, जो कि जब आप CoreGraphics का काम कर रहे होते हैं, तो यह बहुत आसान बात है।
Womble

6

प्रोग्राम के रूप में:

imageView.contentMode = UIViewContentModeScaleAspectFit;

स्टोरीबोर्ड:

यहाँ छवि विवरण दर्ज करें


यह काम करता है, लेकिन मेमोरी के पैरों के निशान को कम करने से, आप बहुत तेजी से लोड हो रहे उदाहरण के लिए ऐप को तेजी से काम कर सकते हैं।
१४

वह UIImageView है, UIImage नहीं है। कभी-कभी, आपको UIImageView के बिना ड्राइंग करने की आवश्यकता होती है।
वुमेबल

5

ठीक है, छवि को आकार देने के लिए हमारे पास कुछ अच्छे उत्तर हैं, लेकिन मैं अपनी आवश्यकता के अनुसार संशोधित करता हूं। आशा है कि यह मेरे जैसे किसी की मदद करेगा।

मेरी आवश्यकता थी

  1. यदि छवि चौड़ाई 1920 से अधिक है, तो इसे 1920 की चौड़ाई के साथ आकार दें और मूल पहलू अनुपात के साथ ऊंचाई बनाए रखें।
  2. यदि छवि की ऊँचाई 1080 से अधिक है, तो इसे 1080 ऊँचाई के साथ आकार दें और मूल पहलू अनुपात के साथ चौड़ाई बनाए रखें।

 if (originalImage.size.width > 1920)
 {
        CGSize newSize;
        newSize.width = 1920;
        newSize.height = (1920 * originalImage.size.height) / originalImage.size.width;
        originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];        
 }

 if (originalImage.size.height > 1080)
 {
            CGSize newSize;
            newSize.width = (1080 * originalImage.size.width) / originalImage.size.height;
            newSize.height = 1080;
            originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];

 }

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

@ श्रीकर अप्पल को धन्यवाद , आकार बदलने के लिए मैंने उनकी विधि का उपयोग किया है।

आपको यह देखना होगा पसंद कर सकते हैं इस रूप में अच्छी तरह आकार गणना के लिए।


4

बस AVFoundation और उपयोग आयात करें AVMakeRectWithAspectRatioInsideRect(CGRectCurrentSize, CGRectMake(0, 0, YOUR_WIDTH, CGFLOAT_MAX)


2

रयान के जवाब में सुधार करने के लिए:

   + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
CGFloat oldWidth = image.size.width;
        CGFloat oldHeight = image.size.height;

//You may need to take some retina adjustments into consideration here
        CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

return [UIImage imageWithCGImage:image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
    }

2
extension UIImage {

    /// Returns a image that fills in newSize
    func resizedImage(newSize: CGSize) -> UIImage? {
        guard size != newSize else { return self }

    let hasAlpha = false
    let scale: CGFloat = 0.0
    UIGraphicsBeginImageContextWithOptions(newSize, !hasAlpha, scale)
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)

        draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }

    /// Returns a resized image that fits in rectSize, keeping it's aspect ratio
    /// Note that the new image size is not rectSize, but within it.
    func resizedImageWithinRect(rectSize: CGSize) -> UIImage? {
        let widthFactor = size.width / rectSize.width
        let heightFactor = size.height / rectSize.height

        var resizeFactor = widthFactor
        if size.height > size.width {
            resizeFactor = heightFactor
        }

        let newSize = CGSize(width: size.width / resizeFactor, height: size.height / resizeFactor)
        let resized = resizedImage(newSize: newSize)

        return resized
    }
}

जब स्केल को 0.0 पर सेट किया जाता है, तो मुख्य स्क्रीन के स्केल कारक का उपयोग किया जाता है, जो रेटिना डिस्प्ले के लिए 2.0 या उच्चतर (iPhone 6 प्लस पर 3.0) है।


1

रयान समाधान @Ryan स्विफ्ट कोड में

उपयोग:

 func imageWithSize(image: UIImage,size: CGSize)->UIImage{
    if UIScreen.mainScreen().respondsToSelector("scale"){
        UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.mainScreen().scale);
    }
    else
    {
         UIGraphicsBeginImageContext(size);
    }

    image.drawInRect(CGRectMake(0, 0, size.width, size.height));
    var newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

//Summon this function VVV
func resizeImageWithAspect(image: UIImage,scaledToMaxWidth width:CGFloat,maxHeight height :CGFloat)->UIImage
{
    let oldWidth = image.size.width;
    let oldHeight = image.size.height;

    let scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

    let newHeight = oldHeight * scaleFactor;
    let newWidth = oldWidth * scaleFactor;
    let newSize = CGSizeMake(newWidth, newHeight);

    return imageWithSize(image, size: newSize);
}

1

में स्विफ्ट 3 कुछ बदलाव कर रहे हैं। यहाँ UIImage का विस्तार दिया गया है:

public extension UIImage {
    public func resize(height: CGFloat) -> UIImage? {
        let scale = height / self.size.height
        let width = self.size.width * scale
        UIGraphicsBeginImageContext(CGSize(width: width, height: height))
        self.draw(in: CGRect(x:0, y:0, width:width, height:height))
        let resultImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resultImage
    }
}

1

जीशान तुफैल और छोटे सुधारों के साथ स्विफ्ट 5 में वोमल जवाब । यहाँ हम maxLengthकिसी भी आयाम और JPEG संपीड़न के लिए छवि पैमाने पर करने के लिए 2 कार्यों के साथ विस्तार किया है ।

extension UIImage {
    func aspectFittedToMaxLengthData(maxLength: CGFloat, compressionQuality: CGFloat) -> Data {
        let scale = maxLength / max(self.size.height, self.size.width)
        let format = UIGraphicsImageRendererFormat()
        format.scale = scale
        let renderer = UIGraphicsImageRenderer(size: self.size, format: format)
        return renderer.jpegData(withCompressionQuality: compressionQuality) { context in
            self.draw(in: CGRect(origin: .zero, size: self.size))
        }
    }
    func aspectFittedToMaxLengthImage(maxLength: CGFloat, compressionQuality: CGFloat) -> UIImage? {
        let newImageData = aspectFittedToMaxLengthData(maxLength: maxLength, compressionQuality: compressionQuality)
        return UIImage(data: newImageData)
    }
}

0

यह एक मेरे लिए एकदम सही था। पहलू अनुपात रखता है और एक लेता है maxLength। चौड़ाई या ऊँचाई से अधिक नहीं होगीmaxLength

-(UIImage*)imageWithImage: (UIImage*) sourceImage maxLength: (float) maxLength
{
    CGFloat scaleFactor = maxLength / MAX(sourceImage.size.width, sourceImage.size.height);

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = sourceImage.size.width * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

0

उपलब्ध चौड़ाई के लिए छवि की सबसे अच्छी ऊंचाई की गणना करता है।

import Foundation

public extension UIImage {
    public func height(forWidth width: CGFloat) -> CGFloat {
        let boundingRect = CGRect(
            x: 0,
            y: 0,
            width: width,
            height: CGFloat(MAXFLOAT)
        )
        let rect = AVMakeRect(
            aspectRatio: size,
            insideRect: boundingRect
        )
        return rect.size.height
    }
}

-1

मैंने इसे बहुत सरल तरीके से हल किया है

UIImage *placeholder = [UIImage imageNamed:@"OriginalImage.png"];
self.yourImageview.image = [UIImage imageWithCGImage:[placeholder CGImage] scale:(placeholder.scale * 1.5)
                                  orientation:(placeholder.imageOrientation)];

स्केल का गुणक छवि के स्केलिंग को परिभाषित करेगा, छवि का गुणक अधिक छोटा होगा। इसलिए आप जांच सकते हैं कि आपकी स्क्रीन क्या है।

या आप इमेजप्लॉइंट / स्क्रीनवॉटर को विभाजित करके गुणक भी प्राप्त कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.