एक UIImage फसल


209

मुझे कुछ कोड मिला है जो एक छवि का आकार देता है ताकि मुझे छवि के केंद्र का एक छोटा हिस्सा मिल सके - मैं इसका उपयोग छवि के UIImageछोटे, चौकोर प्रतिनिधित्व को वापस लेने के लिए करता हूं , जैसा कि एल्बम के दृश्य में देखा गया है तस्वीरें एप्लिकेशन। (मुझे पता है कि मैं एक UIImageViewही परिणाम प्राप्त करने के लिए फसल मोड का उपयोग कर सकता हूं और समायोजित कर सकता हूं , लेकिन ये चित्र कभी-कभी प्रदर्शित होते हैं UIWebViews)।

मैंने इस कोड में कुछ दुर्घटनाओं को नोटिस करना शुरू कर दिया है और मैं थोड़ा स्टम्प्ड हूं। मुझे दो अलग-अलग सिद्धांत मिले हैं और मैं सोच रहा हूं कि क्या आधार है।

सिद्धांत 1) मैं अपने लक्ष्य आकार के ऑफ़स्क्रीन छवि संदर्भ में चित्र बनाकर फसल प्राप्त करता हूं। चूँकि मुझे छवि का केंद्र भाग चाहिए, मैंने CGRectतर्क drawInRectको कुछ इस तरह सेट किया जो मेरी छवि के संदर्भ की सीमा से बड़ा है। मैं उम्मीद कर रहा था कि यह कोशर था, लेकिन क्या मैं इसके बजाय अन्य मेमोरी को खींचने की कोशिश कर रहा हूं, जिन्हें मुझे छूना नहीं चाहिए?

थ्योरी 2) मैं बैकग्राउंड थ्रेड में यह सब कर रहा हूं। मुझे पता है कि UIKit के कुछ भाग हैं जो मुख्य धागे तक ही सीमित हैं। मैं मान रहा था / उम्मीद कर रहा था कि ऑफ़स्क्रीन दृश्य को देखना इनमे से एक नहीं है। क्या मै गलत हु?

(ओह, मैं कैसे NSImage's drawInRect:fromRect:operation:fraction:विधि याद आती है।)


यदि आप किसी दुर्घटना का निदान करने की कोशिश कर रहे हैं, तो आपको डीबगर के तहत ऐप चलाना चाहिए और क्रैश होने पर क्या होता है, इस पर ध्यान देना चाहिए। यदि कोई अपवाद फेंका जा रहा है या आपको झटकेदार सूचक के कारण EXC_BAD_ACCESS हो रहा है, तो भी आपने पहचाना नहीं है। एक बार जब आप यह जान लेंगे, तो आप सिद्धांत बनाना शुरू कर सकते हैं।
बेन्ज़ादो

काफी उचित। मैंने डिबगर के तहत इसे दोबारा नहीं लिया है, हालांकि मेरे पास क्रैश लॉग में EXC_BAD_ACCESS संदेश हैं। जब मैंने इसे पोस्ट किया था, तो मैं इस धारणा के तहत काम कर रहा था कि मैं अपने कार्यान्वयन में एक बेवकूफ गलती करूंगा और कोई व्यक्ति इस पर कूद जाएगा (जैसे कि एक क्लिपिंग मार्ग को भूल जाना)।
जबलेयर

क्या यह लायक और अच्छे जवाब के बावजूद, इसके लिए NSHipster पर तकनीकों और प्रदर्शन का एक अच्छा सर्वेक्षण है: nshipster.com/image-resizing । मुझ में शुद्धतावादी CIImage का उपयोग करना चाहते थे, लेकिन व्यावहारिक ने UIKit / छवि संदर्भ चुना।
क्रिस कॉनोवर

जवाबों:


236

अद्यतन 2014-05-28: मैंने इसे तब लिखा था जब iOS 3 या तो गर्म नई चीज थी, मुझे यकीन है कि अब तक ऐसा करने के बेहतर तरीके हैं, संभवतः बिल्ट-इन। जैसा कि कई लोगों ने उल्लेख किया है, यह विधि रोटेशन को ध्यान में नहीं रखती है; कुछ अतिरिक्त उत्तरों को पढ़ें और इस सवाल के जवाबों को सभी के लिए मददगार बनाए रखने के लिए कुछ प्यार बढ़ाएं।

मूल प्रतिक्रिया:

मैं एक ही प्रश्न को कहीं और अपनी प्रतिक्रिया को कॉपी / पेस्ट करने जा रहा हूं:

ऐसा करने के लिए एक सरल वर्ग विधि नहीं है, लेकिन एक फ़ंक्शन है जिसे आप वांछित परिणाम प्राप्त करने के लिए उपयोग कर सकते हैं: CGImageCreateWithImageInRect(CGImageRef, CGRect)आपकी सहायता करेगा।

इसका उपयोग करते हुए एक छोटा उदाहरण यहां दिया गया है:

CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
// or use the UIImage wherever you like
[UIImageView setImage:[UIImage imageWithCGImage:imageRef]]; 
CGImageRelease(imageRef);

13
जब imageOrientationकिसी भी चीज़ के लिए सेट किया जाता है, लेकिन उसके CGImageसंबंध में घुमाया जाता है UIImageऔर क्रैकिंग आयत गलत होगी। आप क्रॉपिंग आयत को अपने अनुसार घुमा सकते हैं, लेकिन ताज़ा बनाया गया UIImageहोगा imageOrientation, ताकि क्रॉप CGImageको इसके अंदर घुमाया जा सके।
जूल

25
मैं यह बताना चाहता हूं कि रेटिना डिस्प्ले पर आपको इस विधि का उपयोग करके अपनी फसल की चौड़ाई और ऊंचाई को दोगुना करने की आवश्यकता है। बस कुछ मैं भाग गया।
पेट्रोनेट

21
इसे किसी भी अभिविन्यास उपयोग में काम करने के लिए:[UIImage imageWithCGImage:imageRef scale:largeImage.scale orientation:largeImage.imageOrientation];
निकोस करालिस

3
आपको रेटिना के लिए समर्थन जोड़ना चाहिए !!
मेरियो कार्वाल्हो

1
@ निकोसकारलिस जो इसे केवल सही अभिविन्यास में घुमाएगी। हालाँकि, आप छवि से बाहर निकल रहे हैं, वह क्षेत्र अभी भी गलत होगा।
टिम बोदित

90

समान पैमाने और अभिविन्यास रखते हुए रेटिना की छवियों को क्रॉप करने के लिए, UIImage श्रेणी (iOS 4.0 और ऊपर) में निम्न विधि का उपयोग करें:

- (UIImage *)crop:(CGRect)rect {
    if (self.scale > 1.0f) {
        rect = CGRectMake(rect.origin.x * self.scale,
                          rect.origin.y * self.scale,
                          rect.size.width * self.scale,
                          rect.size.height * self.scale);
    }

    CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, rect);
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
    CGImageRelease(imageRef);
    return result;
}

14
तुम बस यहाँ सशर्त मार सकते हैं और हमेशा कई द्वारा self.scale, नहीं?
माइकल मोइर

2
आप ठीक कह रहे हैं, माइकल, लेकिन मुझे लगता है कि उपरोक्त समाधान गैर-रेटिना उपकरणों पर थोड़ा तेज है क्योंकि यह केवल चार गुणा और एक असाइनमेंट के बजाय एक ही चेक करता है। रेटिना-डिवाइसेस पर यह ज़रूरत से ज़्यादा एक एकल बूलियन चेक है, इसलिए यह व्यक्तिगत प्राथमिकता या लक्ष्य फिट का सवाल है।
सीजी

2
क्या CGImageRelease(imageRef);ARC सक्षम के साथ उपयोग करना सही है ?
CGee

3
@Dschee हां। देखें stackoverflow.com/questions/7800174/…
कालरास

3
वास्तव में 4 गुणा एक स्थिति का मूल्यांकन करने से तेज हो सकता है :) आधुनिक सीपीयू पर गुणकों को बहुत अच्छी तरह से अनुकूलित किया जा सकता है जबकि स्थितियों का केवल अनुमान लगाया जा सकता है। लेकिन आप सही हैं, यह प्राथमिकता का विषय है। बढ़ी हुई पठनीयता के कारण मैं छोटा / सरल कोड पसंद करता हूं।
मार्सबियर

65

आप एक UIImage श्रेणी बना सकते हैं और जहाँ भी आपकी आवश्यकता हो, इसका उपयोग कर सकते हैं। HitScans की प्रतिक्रिया और टिप्पणियों के आधार पर यह बंद हो जाता है।

@implementation UIImage (Crop)

- (UIImage *)crop:(CGRect)rect {

    rect = CGRectMake(rect.origin.x*self.scale, 
                      rect.origin.y*self.scale, 
                      rect.size.width*self.scale, 
                      rect.size.height*self.scale);       

    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
    UIImage *result = [UIImage imageWithCGImage:imageRef 
                                          scale:self.scale 
                                    orientation:self.imageOrientation]; 
    CGImageRelease(imageRef);
    return result;
}

@end

आप इसे इस तरह से उपयोग कर सकते हैं:

UIImage *imageToCrop = <yourImageToCrop>;
CGRect cropRect = <areaYouWantToCrop>;   

//for example
//CGRectMake(0, 40, 320, 100);

UIImage *croppedImage = [imageToCrop crop:cropRect];

3
[[UIScreen mainScreen] scale]बस नहीं होना चाहिए self.scale? छवि का पैमाना स्क्रीन के पैमाने के समान नहीं हो सकता है।
माइकल मिऑर

नमस्ते, मैंने आपके उत्तर की कोशिश की और यह मुझे तब No visible @interface for 'UIImage' declares the selector 'crop'भी देता है जब मैंने अपने प्रोजेक्ट में .h और .m श्रेणी की फाइलें डालीं और वर्ग में .h का आयात किया जो मैं श्रेणी का उपयोग कर रहा हूं। कोई उपाय?
अली

ठीक कर दिया। मैं UIImage + Crop.h फ़ाइल में विधि शीर्षलेख को याद करने से चूक गया।
अली

मैं छवि को परिपत्र आकार में क्रॉप करना चाहता हूं। ताकि हम केवल गोलाकार रास्ता देख सकें और अन्य मार्ग पारदर्शी बना रहे।
अल्फ़ा

आप CGImageCreateWithMask या CGImageCreateWithMaskingColors का उपयोग CGImageCreateWithImageInRect
Vilém Kurz

54

स्विफ्ट 3 संस्करण

func cropImage(imageToCrop:UIImage, toRect rect:CGRect) -> UIImage{
    
    let imageRef:CGImage = imageToCrop.cgImage!.cropping(to: rect)!
    let cropped:UIImage = UIImage(cgImage:imageRef)
    return cropped
}


let imageTop:UIImage  = UIImage(named:"one.jpg")! // add validation

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

इस पुल समारोह की मदद से CGRectMake-> CGRect(क्रेडिट इस जवाब से जवाब @rob mayoff):

 func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
    return CGRect(x: x, y: y, width: width, height: height)
}

उपयोग है:

if var image:UIImage  = UIImage(named:"one.jpg"){
   let  croppedImage = cropImage(imageToCrop: image, toRect: CGRectMake(
        image.size.width/4,
        0,
        image.size.width/2,
        image.size.height)
    )
}

आउटपुट:

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


यह सुनिश्चित नहीं था कि इसे क्यों वोट दिया गया था, मुझे लगा कि यह एक अच्छा जवाब है। केवल एक चीज जो मैं सोच सकता हूं कि यह स्केलिंग को हैंडल नहीं करता है, इसलिए यदि आपके पास @ 2x / @ 3x छवियां हैं और यह आपके फ़ंक्शन नामों से मेल नहीं खाता है तो यह काम नहीं करेगा।
विलियम टी।

4
आपको रिटर्न के guardमामले में पहली पंक्ति की आवश्यकता है और जब पूरी तरह से काम करता है तो इसका उपयोग क्यों करें । UIImage.CGImagenilvarlet
NoodleOfDeath

यह सही है, कभी भी, डॉक्स को cropping(to:)बहुत ध्यान से पढ़ें । परिणामस्वरूप CGImageबड़े CGImageसे एक मजबूत संदर्भ रखता है जिसमें से इसे काट दिया गया था। इसलिए यदि आप केवल फसली छवि को लटकाना चाहते हैं और मूल की कोई आवश्यकता नहीं है, तो अन्य समाधानों पर एक नज़र डालें।
21

यह उन छवियों के साथ काम नहीं करता है जिनमें अभिविन्यास टैग हैं। फसल क्षेत्र ठीक से सड़ नहीं पाता है।
मैक्स

1
@ मोम ऐसा इसलिए है क्योंकि cgImage में ओरिएंटेशन सपोर्ट नहीं है। अगर UIImage हो रही है, rightतो cgImage को 90 डिग्री से ccw घुमाया जाना चाहिए, इसलिए फसल की परत को भी घुमाया जाना चाहिए
MK Yung

49

यहाँ मेरा UIImage फसल कार्यान्वयन है जो इमेजऑरिएशन प्रॉपर्टी का पालन करता है। सभी झुकावों का अच्छी तरह से परीक्षण किया गया था।

inline double rad(double deg)
{
    return deg / 180.0 * M_PI;
}

UIImage* UIImageCrop(UIImage* img, CGRect rect)
{
    CGAffineTransform rectTransform;
    switch (img.imageOrientation)
    {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -img.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -img.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -img.size.width, -img.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };
    rectTransform = CGAffineTransformScale(rectTransform, img.scale, img.scale);

    CGImageRef imageRef = CGImageCreateWithImageInRect([img CGImage], CGRectApplyAffineTransform(rect, rectTransform));
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:img.scale orientation:img.imageOrientation];
    CGImageRelease(imageRef);
    return result;
}

7
चेतावनी implicit declaration of function 'rad' is invalid in c99को प्रतिस्थापित करके हटाया जा सकता है: रेड (90), रेड (-90), रेड (-180) -> M_PI_2, -M_PI_2, -_M_PI
साउंड ब्लास्टर

अरे! माफ़ करना। स्रोत स्निपेट में रेड () उपयोगिता फ़ंक्शन जोड़ा गया।
सेर्गी रुडचेंको

contains undefined reference for architecture armv7क्या मुझे एक पुस्तकालय याद आ रहा है? CoreGraphics को आयात किया जाता है।
बॉब स्प्रीएन

1
@SergiiRudchenko "सभी अभिविन्यास का अच्छी तरह से परीक्षण किया गया था।" - क्या इसमें प्रतिबिम्बित अभिविन्यास शामिल हैं?
टिम बोडेट

@BusSpryn नहीं, आप एक पुस्तकालय को याद नहीं कर रहे हैं। हालांकि मैं यह नहीं बता सकता कि त्रुटि का क्या मतलब है, साउंडब्लस्टर जैसा रेड () का प्रतिस्थापन, इस त्रुटि को भी ठीक करता है।
टिम बोदित

39

शीर्षासन: ये सभी उत्तर एक CGImageउलटी छवि वस्तु है।

image.CGImageयदि आप इस छवि का उपयोग कर बनाया UIImageगया है CIImage, जो एक द्वारा समर्थित है , अगर शून्य वापस कर सकते हैं CIFilter

उस स्थिति में, आपको छवि को एक नए संदर्भ में खींचना पड़ सकता है, और उस छवि ( धीमी ) को वापस करना होगा।

UIImage* crop(UIImage *image, rect) {
    UIGraphicsBeginImageContextWithOptions(rect.size, false, [image scale]);
    [image drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)];
    cropped_image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return cropped_image;
}

5
यह वही है जो मुझे चाहिए था, सभी परिदृश्यों में काम करता है इसलिए किसी भी अन्य समाधान से बेहतर है!
डेविड थॉम्पसन

2
Image.size पहली पंक्ति में rect.size UIGraphicsBeginImageContextWithOptions होनी चाहिए (rect.size, false, image.scale);
ब्रेट करें

2
धन्यवाद ब्रेट, निश्चित रूप से वहीं। मैंने इस फिक्स को शामिल करने के लिए कोड को अपडेट किया।
१२:१४ पर १२:१४ पर कोलिंटा

यह सही क्यों है ।origin.x न केवल rect.origin.x?
अग्रेंजी

2
क्योंकि हम फसल काट रहे हैं; दूसरे शब्दों में, 'रेक्ट' arg कह रहा है "मैं चाहता हूं कि नई छवि का शीर्ष-बाईं ओर शुरू हो, कहना, [10, 10]"। ऐसा करने के लिए हम चित्र बनाते हैं ताकि [10, 10] नई छवि के मूल में हो।
कॉलिनटा

35

यहां कोई भी उत्तर सभी पैमाने और रोटेशन के मुद्दों को 100% सही ढंग से नहीं संभालता है। यहां अब तक iOS7 / 8 के रूप में अप-टू-डेट सब कुछ का एक संश्लेषण कहा गया है। यह UIImage पर एक श्रेणी में एक विधि के रूप में शामिल करने के लिए है।

- (UIImage *)croppedImageInRect:(CGRect)rect
{
    double (^rad)(double) = ^(double deg) {
        return deg / 180.0 * M_PI;
    };

    CGAffineTransform rectTransform;
    switch (self.imageOrientation) {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -self.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -self.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -self.size.width, -self.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };
    rectTransform = CGAffineTransformScale(rectTransform, self.scale, self.scale);

    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], CGRectApplyAffineTransform(rect, rectTransform));
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
    CGImageRelease(imageRef);

    return result;
}

1
इस उत्तर को अधिक क्यों नहीं बनाया गया है? मैंने उपरोक्त सभी उत्तरों की कोशिश की और कई टन मुद्दों (विशेष रूप से UIImage से CIImage में परिवर्तित होने और उचित परिवर्तन को खोने) में भाग लिया। यह मेरे लिए केवल एक ही काम है!
अग्रेंजी

1
धन्यवाद @ कांग्रेस, खुशी है कि यह आपके लिए काम करता है। मेरा जवाब केवल एक महीने पहले पोस्ट किया गया था, जबकि इनमें से कई जवाब यहां 5 साल से हैं। मैं अनुमान लगा रहा हूं कि तुलनीय वोटों की कमी बताती है।
जावेद

मैं इसका उपयोग छवियों के पार फिल्टर को स्वाइप करने के लिए कर रहा हूं (जैसे स्नैपचैट कैसे करता है) और मुझे मामूली स्केलिंग मुद्दे मिल रहे हैं। क्या आपके कोड में कुछ भी है जो मैं सुझाव दे सकता हूं कि मैं इस स्केलिंग त्रुटि का कारण क्या हो सकता है? मैंने अपना समाधान पोस्ट किया है जो आपके कोड का उपयोग यहां करता है: stackoverflow.com/questions/23319497/…
अग्रसेन

एक बहुत ही उपयोगी कार्य, धन्यवाद। छवि के मध्य भाग पर ध्यान केंद्रित करते हुए किसी भी सुझाव को फसल में संशोधित किया जाना चाहिए?
प्राइवेट

इस प्रति को होना चाहिए।
घोड़े की नाल 7

17

awolfमेरे लिए काम करने वाले उत्तर का स्विफ्ट संस्करण :

public extension UIImage {
    func croppedImage(inRect rect: CGRect) -> UIImage {
        let rad: (Double) -> CGFloat = { deg in
            return CGFloat(deg / 180.0 * .pi)
        }
        var rectTransform: CGAffineTransform
        switch imageOrientation {
        case .left:
            let rotation = CGAffineTransform(rotationAngle: rad(90))
            rectTransform = rotation.translatedBy(x: 0, y: -size.height)
        case .right:
            let rotation = CGAffineTransform(rotationAngle: rad(-90))
            rectTransform = rotation.translatedBy(x: -size.width, y: 0)
        case .down:
            let rotation = CGAffineTransform(rotationAngle: rad(-180))
            rectTransform = rotation.translatedBy(x: -size.width, y: -size.height)
        default:
            rectTransform = .identity
        }
        rectTransform = rectTransform.scaledBy(x: scale, y: scale)
        let transformedRect = rect.applying(rectTransform)
        let imageRef = cgImage!.cropping(to: transformedRect)!
        let result = UIImage(cgImage: imageRef, scale: scale, orientation: imageOrientation)
        return result
    }
}

10
CGSize size = [originalImage size];
int padding = 20;
int pictureSize = 300;
int startCroppingPosition = 100;
if (size.height > size.width) {
    pictureSize = size.width - (2.0 * padding);
    startCroppingPosition = (size.height - pictureSize) / 2.0; 
} else {
    pictureSize = size.height - (2.0 * padding);
    startCroppingPosition = (size.width - pictureSize) / 2.0;
}
// WTF: Don't forget that the CGImageCreateWithImageInRect believes that 
// the image is 180 rotated, so x and y are inverted, same for height and width.
CGRect cropRect = CGRectMake(startCroppingPosition, padding, pictureSize, pictureSize);
CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], cropRect);
UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:originalImage.imageOrientation];
[m_photoView setImage:newImage];
CGImageRelease(imageRef);

अधिकांश प्रतिक्रियाओं को मैंने केवल (x, y) के लिए (0, 0) की स्थिति के साथ देखा है। ठीक है कि एक मामला है, लेकिन मैं अपने क्रॉपिंग ऑपरेशन को केंद्रित करना चाहूंगा। मुझे यह पता लगाने में थोड़ी देर लगी कि डब्ल्यूटीएफ की टिप्पणी के बाद कौन सी लाइन है।

आइए एक चित्र अभिविन्यास के साथ कैप्चर की गई छवि का मामला लें:

  1. मूल छवि की ऊँचाई इसकी चौड़ाई से अधिक है (वू, अब तक कोई आश्चर्य नहीं!)
  2. छवि जो CGImageCreateWithImageInRect पद्धति की अपनी दुनिया में कल्पना करती है, वह वास्तव में एक चित्र नहीं है, लेकिन एक परिदृश्य है (यही कारण है कि यदि आप imageWithCGImage कंस्ट्रक्टर में ओरिएंटेशन तर्क का उपयोग नहीं करते हैं, तो यह 180 घुमाए गए के रूप में दिखाई देगा)।
  3. तो, आपको कल्पना करना चाहिए कि यह एक परिदृश्य है, (0, 0) स्थिति छवि के शीर्ष दाएं कोने में है।

आशा है कि यह समझ में आता है! यदि ऐसा नहीं होता है, तो अलग-अलग मानों को आज़माएँ, आप देखेंगे कि जब आपकी फसल के लिए सही x, y, चौड़ाई, और ऊँचाई चुनने की बात आती है तो तर्क उल्टा हो जाता है।


8

swift3

extension UIImage {
    func crop(rect: CGRect) -> UIImage? {
        var scaledRect = rect
        scaledRect.origin.x *= scale
        scaledRect.origin.y *= scale
        scaledRect.size.width *= scale
        scaledRect.size.height *= scale
        guard let imageRef: CGImage = cgImage?.cropping(to: scaledRect) else {
            return nil
        }
        return UIImage(cgImage: imageRef, scale: scale, orientation: imageOrientation)
    }
}

7

स्विफ्ट एक्सटेंशन

extension UIImage {
    func crop(var rect: CGRect) -> UIImage {
        rect.origin.x*=self.scale
        rect.origin.y*=self.scale
        rect.size.width*=self.scale
        rect.size.height*=self.scale

        let imageRef = CGImageCreateWithImageInRect(self.CGImage, rect)
        let image = UIImage(CGImage: imageRef, scale: self.scale, orientation: self.imageOrientation)!
        return image
    }
}

4

सटीक, पिक्सेल स्केलिंग की अवधि में स्विफ्ट में एक UIImage फसल के लिए सबसे अच्छा समाधान ...:

private func squareCropImageToSideLength(let sourceImage: UIImage,
    let sideLength: CGFloat) -> UIImage {
        // input size comes from image
        let inputSize: CGSize = sourceImage.size

        // round up side length to avoid fractional output size
        let sideLength: CGFloat = ceil(sideLength)

        // output size has sideLength for both dimensions
        let outputSize: CGSize = CGSizeMake(sideLength, sideLength)

        // calculate scale so that smaller dimension fits sideLength
        let scale: CGFloat = max(sideLength / inputSize.width,
            sideLength / inputSize.height)

        // scaling the image with this scale results in this output size
        let scaledInputSize: CGSize = CGSizeMake(inputSize.width * scale,
            inputSize.height * scale)

        // determine point in center of "canvas"
        let center: CGPoint = CGPointMake(outputSize.width/2.0,
            outputSize.height/2.0)

        // calculate drawing rect relative to output Size
        let outputRect: CGRect = CGRectMake(center.x - scaledInputSize.width/2.0,
            center.y - scaledInputSize.height/2.0,
            scaledInputSize.width,
            scaledInputSize.height)

        // begin a new bitmap context, scale 0 takes display scale
        UIGraphicsBeginImageContextWithOptions(outputSize, true, 0)

        // optional: set the interpolation quality.
        // For this you need to grab the underlying CGContext
        let ctx: CGContextRef = UIGraphicsGetCurrentContext()
        CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh)

        // draw the source image into the calculated rect
        sourceImage.drawInRect(outputRect)

        // create new image from bitmap context
        let outImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()

        // clean up
        UIGraphicsEndImageContext()

        // pass back new image
        return outImage
}

इस फ़ंक्शन को कॉल करने के लिए उपयोग किए जाने वाले निर्देश:

let image: UIImage = UIImage(named: "Image.jpg")!
let squareImage: UIImage = self.squareCropImageToSideLength(image, sideLength: 320)
self.myUIImageView.image = squareImage

नोट: उद्देश्य-सी में लिखे गए प्रारंभिक स्रोत कोड प्रेरणा "कोकोनेटिक्स" ब्लॉग पर पाए गए हैं।


3

नीचे कोड स्निपेट मदद कर सकता है।

import UIKit

extension UIImage {
    func cropImage(toRect rect: CGRect) -> UIImage? {
        if let imageRef = self.cgImage?.cropping(to: rect) {
            return UIImage(cgImage: imageRef)
        }
        return nil
    }
}

2

थोड़ा अजीब लग रहा है, लेकिन महान काम करता है और छवि अभिविन्यास में लेता है:

var image:UIImage = ...

let img = CIImage(image: image)!.imageByCroppingToRect(rect)
image = UIImage(CIImage: img, scale: 1, orientation: image.imageOrientation)

1
लेकिन यह स्पष्ट रूप से पैमाने तोड़ता है
सुल्तान

2

स्विफ्ट 5:

extension UIImage {
    func cropped(rect: CGRect) -> UIImage? {
        guard let cgImage = cgImage else { return nil }

        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        let context = UIGraphicsGetCurrentContext()

        context?.translateBy(x: 0.0, y: self.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        context?.draw(cgImage, in: CGRect(x: rect.minX, y: rect.minY, width: self.size.width, height: self.size.height), byTiling: false)


        let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return croppedImage
    }
}

1
- (UIImage *)getSubImage:(CGRect) rect{
    CGImageRef subImageRef = CGImageCreateWithImageInRect(self.CGImage, rect);
    CGRect smallBounds = CGRectMake(rect.origin.x, rect.origin.y, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));

    UIGraphicsBeginImageContext(smallBounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, smallBounds, subImageRef);
    UIImage* smallImg = [UIImage imageWithCGImage:subImageRef];
    UIGraphicsEndImageContext();

    return smallImg;
}

1
 (UIImage *)squareImageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    double ratio;
    double delta;
    CGPoint offset;

    //make a new square size, that is the resized imaged width
    CGSize sz = CGSizeMake(newSize.width, newSize.width);

    //figure out if the picture is landscape or portrait, then
    //calculate scale factor and offset
    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);
    }

    //make the final clipping rect based on the calculated values
    CGRect clipRect = CGRectMake(-offset.x, -offset.y,
                                 (ratio * image.size.width) + delta,
                                 (ratio * image.size.height) + delta);


    //start a new context, with scale factor 0.0 so retina displays get
    //high quality image
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0);
    } else {
        UIGraphicsBeginImageContext(sz);
    }
    UIRectClip(clipRect);
    [image drawInRect:clipRect];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

1

IOS9.2SDK पर, मैं UIView से UIImage में फ्रेम बदलने के लिए नीचे विधि का उपयोग करता हूं

-(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
{
  CGSize cropSize = rect.size;
  CGFloat widthScale = image.size.width/self.imageViewOriginal.bounds.size.width;
  CGFloat heightScale = image.size.height/self.imageViewOriginal.bounds.size.height;
  cropSize = CGSizeMake(rect.size.width*widthScale, 
              rect.size.height*heightScale);
  CGPoint pointCrop = CGPointMake(rect.origin.x*widthScale,
             rect.origin.y*heightScale);
  rect = CGRectMake(pointCrop.x, pointCrop.y, cropSize.width, cropSize.height);
  CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
  UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
  CGImageRelease(subImage);

  return croppedImage;
}

1

स्विफ्ट 2.0 अपडेट ( CIImageसंगतता)

मैक्सिम के उत्तर का विस्तार लेकिन काम करता है अगर आपकी छवि CIImageआधारित है, साथ ही।

public extension UIImage {
    func imageByCroppingToRect(rect: CGRect) -> UIImage? {
        if let image = CGImageCreateWithImageInRect(self.CGImage, rect) {
            return UIImage(CGImage: image)
        } else if let image = (self.CIImage)?.imageByCroppingToRect(rect) {
            return UIImage(CIImage: image)
        }
       return nil
   }
}

1

यहाँ के आधार पर एक अद्यतन स्विफ्ट 3 संस्करण है नूडल्स जवाब

func cropping(to rect: CGRect) -> UIImage? {

    if let cgCrop = cgImage?.cropping(to: rect) {
        return UIImage(cgImage: cgCrop)
    }
    else if let ciCrop = ciImage?.cropping(to: rect) {
        return UIImage(ciImage: ciCrop)
    }

    return nil
}

1

@ उत्तर का पालन करें। मैं सिर्फ श्रेणी समारोह के लिए फिक्सिंग। इसे UIImage की श्रेणी में रखें।

-(UIImage*)cropImage:(CGRect)rect{

    UIGraphicsBeginImageContextWithOptions(rect.size, false, [self scale]);
    [self drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)];
    UIImage* cropped_image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return cropped_image;
}

0

मैं अन्य समाधानों से संतुष्ट नहीं था क्योंकि वे या तो कई बार आकर्षित होते हैं (आवश्यकता से अधिक शक्ति का उपयोग करते हुए) या अभिविन्यास के साथ समस्याएं होती हैं। यहाँ है कि मैं एक UIImage * छवि से एक छोटा वर्ग क्रॉपइमेज के लिए क्या उपयोग करता हूं।

CGFloat minimumSide = fminf(image.size.width, image.size.height);
CGFloat finalSquareSize = 600.;

//create new drawing context for right size
CGRect rect = CGRectMake(0, 0, finalSquareSize, finalSquareSize);
CGFloat scalingRatio = 640.0/minimumSide;
UIGraphicsBeginImageContext(rect.size);

//draw
[image drawInRect:CGRectMake((minimumSide - photo.size.width)*scalingRatio/2., (minimumSide - photo.size.height)*scalingRatio/2., photo.size.width*scalingRatio, photo.size.height*scalingRatio)];

UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

0

मैं नीचे दी गई विधि का उपयोग करता हूं।

  -(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
  {
    CGSize cropSize = rect.size;
    CGFloat widthScale =  
    image.size.width/self.imageViewOriginal.bounds.size.width;
    CGFloat heightScale = 
    image.size.height/self.imageViewOriginal.bounds.size.height;
    cropSize = CGSizeMake(rect.size.width*widthScale,  
    rect.size.height*heightScale);
    CGPoint  pointCrop = CGPointMake(rect.origin.x*widthScale, 
    rect.origin.y*heightScale);
    rect = CGRectMake(pointCrop.x, pointCrop.y, cropSize.width, 
    cropSize.height);
    CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
    UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
    CGImageRelease(subImage);
    return croppedImage;

}


0

Https://github.com/vvbogdan/BVCropPhoto को देखें

- (UIImage *) क्रॉपइमेज {
    CGFloat पैमाना = self.sourceImage.size. उपलब्धता / self.scrollView.contentSize. उपलब्धता;

    UIImage * finalImage = nil;
    CGRect targetFrame = CGRectMake ((self.scrollView.contentInset.left + self.scrollView.contentOffset.x) * स्केल
            (self.scrollView.contentInset.top + self.scrollView.contentOffset.y) * स्केल
            self.cropSize.width * स्केल,
            self.cropSize.height * स्केल);

    CGImageRef referenceImage = CGImageCreateWithImageInRect ([[सेल्फ इमेजथ्रोटेशन: self.sourceImage] CGImage], targetFrame);

    अगर (संदर्भ)! = NULL) {
        FinalImage = [UIImage imageWithCGImage: referenceImage
                                         पैमाने: self.sourceImage.scale
                                   उन्मुखीकरण: UIImageOrientationUp];

        CGImageRelease (contextImage);
    }

    रिटर्न फाइनल
}


- (UIImage *) छविवितरण: (UIImage *) छवि {


    if (image.imageOrientation == UIImageOrientationUp) वापसी छवि;
    CGAffineTransform रूपांतर = CGAffineTransformIdentity;

    स्विच (image.imageOrientation) {
        मामला UIImageOrientationDown:
        मामला UIImageOrientationDownMirrored:
            ट्रांस्फ़ॉर्म = CGAffineTransformTranslate (रूपांतर, image.size.width, image.size.height);
            बदलना = CGAffineTransformRotate (परिवर्तन, M_PI);
            टूटना;

        मामला UIImageOrientationLeft:
        मामला UIImageOrientationLeftMirrored:
            ट्रांस्फ़ॉर्म = CGAffineTransformTranslate (रूपांतर, छवि। आकार, जोखिम, 0);
            बदलना = CGAffineTransformRotate (परिवर्तन, M_PI_2);
            टूटना;

        मामला UIImageOrientationRight:
        मामला UIImageOrientationRightMirrored:
            ट्रांस्फ़ॉर्म = CGAffineTransformTranslate (रूपांतर, 0, छवि। आकार)
            बदलना = CGAffineTransformRotate (परिवर्तन, -M_PI_2);
            टूटना;
        मामला UIImageOrientationUp:
        मामला UIImageOrientationUpMirrored:
            टूटना;
    }

    स्विच (image.imageOrientation) {
        मामला UIImageOrientationUpMirrored:
        मामला UIImageOrientationDownMirrored:
            ट्रांस्फ़ॉर्म = CGAffineTransformTranslate (रूपांतर, छवि। आकार, जोखिम, 0);
            बदलना = CGAffineTransformScale (परिवर्तन, -1, 1);
            टूटना;

        मामला UIImageOrientationLeftMirrored:
        मामला UIImageOrientationRightMirrored:
            ट्रांस्फ़ॉर्म = CGAffineTransformTranslate (रूपांतर, छवि। साइज़। हाइट, 0);
            बदलना = CGAffineTransformScale (परिवर्तन, -1, 1);
            टूटना;
        मामला UIImageOrientationUp:
        मामला UIImageOrientationDown:
        मामला UIImageOrientationLeft:
        मामला UIImageOrientationRight:
            टूटना;
    }

    // अब हम ट्रांसफॉर्मेशन को लागू करते हुए अंतर्निहित CGImage को एक नए संदर्भ में आकर्षित करते हैं
    // ऊपर की गणना।
    CGContextRef ctx = CGBitmapContextCreate (NULL, image.size.width, image.size.height)
            CGImageGetBitsPerComponent (image.CGImage), 0,
            CGImageGetColorSpace (image.CGImage),
            CGImageGetBitmapInfo (image.CGImage));
    CGContextConcatCTM (ctx, transform);
    स्विच (image.imageOrientation) {
        मामला UIImageOrientationLeft:
        मामला UIImageOrientationLeftMirrored:
        मामला UIImageOrientationRight:
        मामला UIImageOrientationRightMirrored:
            // जीआरआर ...
            CGContextDrawImage (ctx, CGRectMake (0, 0, image.size.height, image.size. उपलब्धता), image.CGImage);
            टूटना;

        चूक:
            CGContextDrawImage (ctx, CGRectMake (0, 0, image.size.width, image.size.height), image.CGImage);
            टूटना;
    }

    // और अब हम सिर्फ ड्राइंग संदर्भ से एक नया UIImage बनाते हैं
    CGImageRef cgimg = CGBitmapContextCreateImage (ctx);
    UIImage * img = [UIImage imageWithCGImage: cgimg];
    CGContextRelease (ctx);
    CGImageRelease (cgimg);
    वापसी img;

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