একটি ইউআইআইমেজ ক্রপ করা হচ্ছে


209

আমি কিছু কোড পেয়েছি যা একটি চিত্রকে আকার দেয় যাতে আমি চিত্রের কেন্দ্রের একটি ছোট অংশ পেতে পারি - আমি এটি ব্যবহার করতে UIImageএবং একটি চিত্রের একটি ছোট, বর্গক্ষেত্র উপস্থাপনা ফিরিয়ে আনতে ব্যবহার করি, এর অ্যালবাম ভিউতে যা দেখা যায় তার সমান ফটো অ্যাপ্লিকেশন। (আমি জানি UIImageViewযে একই ফলাফল অর্জনের জন্য আমি ক্রপ মোডকে ব্যবহার করতে পারি এবং সামঞ্জস্য করতে পারি, তবে এই চিত্রগুলি মাঝে মাঝে প্রদর্শিত হয় UIWebViews)।

আমি এই কোডটিতে কিছু ক্র্যাশ লক্ষ্য করতে শুরু করেছি এবং আমি কিছুটা স্ট্যাম্পড। আমি দুটি পৃথক তত্ত্ব পেয়েছি এবং আমি ভাবছি যদি হয় ভিত্তি হয় কিনা।

থিওরি 1) আমি আমার টার্গেট সাইজের অফস্ক্রিন চিত্রের প্রসঙ্গ এঁকে দিয়ে ফসল অর্জন করি। যেহেতু আমি চিত্রের কেন্দ্র অংশ চাই, তাই আমি CGRectযুক্তিটি drawInRectআমার চিত্রের প্রসঙ্গে সীমার চেয়ে বড় কিছুতে সেট করে দিয়েছি । আমি আশা করছিলাম এটি কোশর, তবে আমি কি পরিবর্তে অন্য স্মৃতিটি আঁকবার চেষ্টা করছি যা আমার স্পর্শ করা উচিত নয়?

থিওরি 2) আমি ব্যাকগ্রাউন্ড থ্রেড এ সব করছি। আমি জানি ইউআইকিটির এমন কিছু অংশ রয়েছে যা মূল থ্রেডে সীমাবদ্ধ। আমি ধরে নিচ্ছিলাম / আশা করছি যে কোনও অফস্ক্রিন ভিউ আঁকানো এর মধ্যে একটি নয়। আমি কি ভূল?

(ওহ, আমি কীভাবে NSImage's drawInRect:fromRect:operation:fraction:পদ্ধতিটি মিস করি ))


আপনি যদি ক্র্যাশ সনাক্ত করার চেষ্টা করছেন, আপনার ডিবাগারের অধীনে অ্যাপটি চালানো উচিত এবং ক্রাশ হওয়ার পরে কী ঘটে তা নোট করে রাখুন। এমনকি কোনও ব্যতিক্রম ছোঁড়া হচ্ছে কিনা তা আপনি সনাক্ত করতে পারেন না বা ঝুঁকির পয়েন্টারের কারণে আপনি EXC_BAD_ACCESS পাচ্ছেন। একবার আপনি এটি জানতে পারবেন, তারপরে আপনি তত্ত্বগুলি তৈরি করা শুরু করতে পারেন।
বেনজাদো

যথেষ্ট ফর্সা। আমি এটি ডিবাগারের অধীনে পুনরায় প্রতিস্থাপন করিনি, যদিও ক্র্যাশ লগটিতে আমার কাছে EXC_BAD_ACCESS বার্তা রয়েছে। আমি যখন এটি পোস্ট করেছি তখন আমি এই ধারণার অধীনে কাজ করছিলাম যে আমি আমার বাস্তবায়নে একটি বোকা ভুল করেছি এবং কেউ এটির উপরে ঝাঁপিয়ে পড়বে (যেমন একটি ক্লিপিংয়ের পথ ভুলে যাওয়া)।
জব্লায়ার

এটি মূল্যবান এবং ভাল উত্তরের নীচে সত্ত্বেও, এনএসএইচএসটারে এর কৌশলগুলি এবং কার্য সম্পাদনের একটি ভাল সমীক্ষা রয়েছে: nshipster.com/image-resizing । আমার মধ্যে পিউরিস্ট সিআইআইমেজটি ব্যবহার করতে চেয়েছিল, তবে বাস্তববাদী ইউআইকিট / চিত্রের প্রসঙ্গটি বেছে নিয়েছে।
ক্রিস কনভার ২

উত্তর:


236

আপডেট 2014-05-28: আইওএস 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

একই স্কেল এবং অভিমুখীকরণের সময় রেটিনা চিত্রগুলি ক্রপ করতে, ইউআইআইমেজ বিভাগে (আইওএস 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);এটিআরসি সক্ষম করে ব্যবহার করা ঠিক কি ?
সিজিআই

3
হ্যাঁ দেখুন stackoverflow.com/questions/7800174/...
Klaas

3
প্রকৃতপক্ষে 4 টি গুণগুলি একটি শর্তের মূল্যায়নের চেয়ে দ্রুত হতে পারে :) আধুনিক সিপিইউগুলিতে গুণগুলি বেশ ভালভাবে অনুকূল করা যায় যেখানে শর্তগুলির পূর্বাভাস দেওয়া যায়। তবে আপনি ঠিক বলেছেন, এটি পছন্দ করার বিষয়। আমি বর্ধিত পাঠযোগ্যতার কারণে সংক্ষিপ্ত / সহজ কোডটি পছন্দ করি।
মার্সবিয়ার

65

আপনি একটি ইউআইআইমেজ বিভাগ তৈরি করতে পারেন এবং যেখানে আপনার প্রয়োজন সেখানে এটি ব্যবহার করতে পারেন। হিটস্ক্যান্সের প্রতিক্রিয়া এবং মন্তব্যের ভিত্তিতে এটি প্রশংসনীয়।

@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 আমদানি করছি আমি বিভাগটি ব্যবহার করছি। কোন ধারণা?
আলী

ঠিক কর. আমি পদ্ধতিটি শিরোনামটি ইউআইআইএমেজ + ক্রপ এইচ।
আলী

আমি বৃত্তাকার আকারে চিত্র ক্রপ করতে চাই। যাতে আমরা কেবলমাত্র বৃত্তাকার পথ দেখতে পাই এবং অন্যান্য পথটি স্বচ্ছ থাকে।
আলফা

আপনি সিজিএমেজক্রিয়াট উইথমাস্ক বা সিজি ইমেজক্রিয়াট উইথ ম্যাসক্লিংয়ের পরিবর্তে সিজিমেজক্রিয়াট উইথ ইমেজইনরেট ব্যবহার করতে পারবেন
ভিলম কুর্জ

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
নুডলঅফডিথ

এটি ঠিক, তবুও ডক্সটি cropping(to:)খুব সাবধানতার সাথে পড়ুন। ফলস্বরূপ CGImageবৃহত্তর CGImageথেকে এটি কাটা হয়েছে একটি শক্তিশালী রেফারেন্স ধারণ করে । সুতরাং আপনি যদি কেবল ক্রপযুক্ত চিত্রটিতে স্থির থাকতে চান এবং আসলটির কোনও প্রয়োজন না থেকে থাকে তবে অন্যান্য সমাধানগুলি দেখুন।
jsadler

ওরিয়েন্টেশন ট্যাগ রয়েছে এমন চিত্রগুলির সাথে এটি কাজ করে না। শস্য অঞ্চলটি সঠিকভাবে আবর্তিত হয় না।
সর্বোচ্চ

1
@ ম্যাক্স এটি কারণ সিজিআইমেজ এর ওরিয়েন্টেশন সমর্থন নেই। ইউআইআইমেজ যদি থাকে rightতবে সিজিআইমেজটি 90 ডিগ্রি দ্বারা সিসিডব্লু ঘোরানো উচিত, সুতরাং ফসলের রেক্টটিও ঘোরানো উচিত
এম কে ইয়ং

49

এখানে আমার ইউআইআইমেজ ফসলের বাস্তবায়ন যা চিত্র ওরিয়েন্টেশন সম্পত্তি অনুসরণ করে। সমস্ত ওরিয়েন্টেশন পুঙ্খানুপুঙ্খভাবে পরীক্ষা করা হয়েছিল।

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) -> এম_পিআই_2, -এমপিআই_2, -_এমপিআই
সাউন্ড ব্লাস্টার

ওহো দুঃখিত. উত্স স্নিপেটে রেড () ইউটিলিটি ফাংশন যুক্ত করেছে।
সের্গেই রুদচেনকো

contains undefined reference for architecture armv7আমি কি একটি গ্রন্থাগার মিস করছি? কোর গ্রাফিক্স আমদানি করা হয়।
বব স্প্রইন

1
@ সার্জিই রুডচেনকো "সমস্ত দিকনির্দেশনা পুরোপুরি পরীক্ষা করা হয়েছিল।" - এর মধ্যে কি মিররযুক্ত ওরিয়েন্টেশন অন্তর্ভুক্ত রয়েছে?
টিম বোডিট

@ BobSpryn না আপনি একটি লাইব্রেরি মিস করছেন না। আমি ত্রুটিটির অর্থ কী তা ব্যাখ্যা করতে পারছি না, তবে সাউন্ডব্লাস্টারের প্রস্তাবিত রেড () এর প্রতিস্থাপনও এই ত্রুটিটিকেও ঠিক করে দিয়েছে।
টিম বোডিট

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
ইমেজ.সাইজটি প্রথম লাইনে রেকট করা উচিত U
ব্রেট

2
ধন্যবাদ ব্রেট, অবশ্যই সেখানে। এই সংশোধনটি অন্তর্ভুক্ত করার জন্য আমি কোডটি আপডেট করেছি।
কলিন্টা

কেন এটি সঠিক.অরগিন.এক্স কেবলমাত্র rect.origin.x নয়?
আগ্রাসী

2
কারণ আমরা ফসল কাটছি; অন্য কথায়, 'রেক্টর' আরগটি বলছে "আমি চাই নতুন চিত্রের উপরের-বামটি শুরু করুন, বলুন, [10, 10]"। এটি করার জন্য আমরা চিত্রটি এঁকেছি যাতে [10, 10] নতুন চিত্রের উত্সে থাকে।
কলিন্টা

35

এখানে উত্তরগুলির কোনওোটাই 100% সঠিকভাবে স্কেল এবং আবর্তনের সমস্যাগুলি পরিচালনা করে না। আইওএস 7/8-তে এখন পর্যন্ত যা কিছু বলা হয়েছে তার সংশ্লেষণ এখানে। এটি ইউআইআইমেজে একটি বিভাগে একটি পদ্ধতি হিসাবে অন্তর্ভুক্ত বোঝানো হয়েছে।

- (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
কেন এই উত্তরটি বেশি উত্সাহিত করা হয় না? আমি উপরের সমস্ত উত্তর চেষ্টা করে দেখেছি এবং প্রচুর সংখ্যক ইস্যুতে ছড়িয়ে পড়েছি (উল্লেখযোগ্যভাবে ইউআইআইমেজ থেকে সিআইআইমেজে রূপান্তর করা এবং সঠিক রূপান্তর ডেটা হারাতে)। এটি কেবল আমার জন্য কাজ করে!
আগ্রাসক

1
ধন্যবাদ @ অ্যাগ্র্রেসর, খুশী এটি আপনার জন্য কাজ করে। আমার উত্তরটি কেবল এক মাস আগে পোস্ট করা হয়েছিল যেখানে এর উত্তরগুলির অনেকগুলি এখানে 5 বছর ধরে রয়েছে। আমি অনুমান করছি যে তুলনামূলকভাবে ভোটের অভাবকে ব্যাখ্যা করে।
অজলফ

আমি এটি চিত্রগুলির জুড়ে ফিল্টারগুলি সোয়াইপ করতে ব্যবহার করছি (যেমন স্ন্যাপচ্যাট কী করে) এবং আমি সামান্য স্কেলিংয়ের সমস্যা পাচ্ছি। আপনার কোডে এমন কোনও কি আছে যা আপনি প্রস্তাব করতে পারেন যে আমি এই স্কেলিং ত্রুটির কারণটি ধরে রাখতে পারি সেদিকে নজর দেওয়া উচিত? আমি আমার সমাধান পোস্ট করেছি যা এখানে আপনার কোড ব্যবহার করে: স্ট্যাকওভারফ্লো
আগ্রাসক

একটি খুব দরকারী ফাংশন, আপনাকে ধন্যবাদ। কোন টিপস চিত্রের কেন্দ্রীয় অংশে ফোকাস করে ফসল পরিবর্তন করতে হবে?
ব্যক্তিগত

এই উত্তর দেওয়া উচিত।
অশ্বশী 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. সিজিআইমেজক্রিয়াট উইথআইমেজইনরেট পদ্ধতিটি নিজের পৃথিবীতে যে চিত্রটি কল্পনা করে তা সত্যই প্রতিকৃতি নয় তবে একটি ল্যান্ডস্কেপ (এটি কারণ আপনি যদি চিত্রের সাথে উইথসিজিআইজি কনস্ট্রাক্টারে ওরিয়েন্টেশন আর্গুমেন্টটি ব্যবহার না করেন তবে এটি 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- তে আমি ইউআইভিউ থেকে ইউআইআইজেমে ফ্রেম রূপান্তর করতে নীচের পদ্ধতিটি ব্যবহার করি

-(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

সুইফট ২.০ আপডেট ( 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*)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

আমি অন্যান্য সমাধানগুলিতে সন্তুষ্ট নই কারণ তারা হয় বেশ কয়েকটি সময় আঁকেন (প্রয়োজনীয়তার চেয়ে বেশি শক্তি ব্যবহার করে) বা অভিমুখীকরণে সমস্যা রয়েছে। আমি এখানে একটি UII छवि * চিত্র থেকে বর্ধিত বর্গক্ষেত্রযুক্ত ক্রপযুক্ত চিত্রের জন্য যা ব্যবহার করেছি।

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

- (ইউআইআইএমেজ *) ক্রপডআইমেজ {
    সিজিফ্লোট স্কেল = সেলফসোর্সআইমেজ.সাইজ.উইথ / সেলফস্ক্রোলভিউ.কন্টেন্টসাইজ.উইথ;

    ইউআইআইমেজ * ফাইনাল ইমেজ = শূন্য;
    সিজিআরেক্ট টার্গেটফ্রেম = সিজিআরেক্টমেক ((স্বতঃস্ক্রোলভিউ। কন্টেন্টআইনসেট.লেফ্ট + সেলফ.স্ক্রোলভিউ.কন্টেন্টঅফসেট.এক্স)) স্কেল,
            (স্ব.স্ক্রোলভিউ.কন্টেন্টইনসেট.টপ + সেলফ.স্ক্রোলভিউ। কন্টেন্টঅফসেট.ই) * স্কেল,
            self.cropSize.width * স্কেল,
            self.cropSize.height * স্কেল);

    সিজিআইমেজআরএফ প্রসঙ্গ

    যদি (প্রসঙ্গের চিত্র! = নুল) {
        ফাইনাল ইমেজ = [ইউআইআইমেজ ইমেজ উইথ সিজি ইমেজ: কনটেক্সট ইমেজ
                                         স্কেল: self.sourceImage.scale
                                   অভিযোজন: UIImageOrientationUp];

        CGImageRelease (contextImage);
    }

    প্রত্যাবর্তন চূড়ান্ত চিত্র;
}


- (UII छवि *) চিত্রবিহীন রোটেশন: (UII छवि *) চিত্র {


    যদি (image.imageOrientation == UIImageOrientationUp) চিত্র ফিরে আসে;
    সিজিএফাইনট্রান্সফর্ম রূপান্তর = সিজিএফাইনট্রান্সফর্মআইডেন্টিটি;

    স্যুইচ (image.imageOrientation) {
        কেস ইউআইজিমেজ ওরিয়েন্টেশন ডাউন:
        কেসআইআইআইজিওরিয়েন্টেশনডাউন মিররড:
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম ট্রান্সলেট (রূপান্তর, ইমেজ.সাইজ.উইথ, ইমেজ.সাইজ.হাইট);
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম রোটেট (ট্রান্সফর্ম, এমএপিআই);
            বিরতি;

        কেস ইউআইজিমেজ ওরিয়েন্টেশন লেফট:
        কেস ইউআইআইজিওরিয়েন্টেশন লেফট মিররড:
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম ট্রান্সলেট (রূপান্তর, চিত্র.সাইজ.উইথথ, 0);
            ট্রান্সফর্ম = সিজিএফাইন ট্রান্সফর্ম রোটেট (ট্রান্সফর্ম, এম_PI_2);
            বিরতি;

        কেসআইআইআইজিএজ ওরিয়েন্টেশন রাইট:
        কেসআইআইআইজিএইজ ওরিয়েন্টেশন
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম ট্রান্সলেট (রূপান্তর, 0, ইমেজ.সাইজ.হাইট);
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম রোটেট (রূপান্তর, -M_PI_2);
            বিরতি;
        কেস ইউআইজিএজ ওরিয়েন্টেশনআপ:
        কেস ইউআইজিএজ ওরিয়েন্টেশন আপ মিররড:
            বিরতি;
    }

    স্যুইচ (image.imageOrientation) {
        কেস ইউআইজিএজ ওরিয়েন্টেশন আপ মিররড:
        কেসআইআইআইজিওরিয়েন্টেশনডাউন মিররড:
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম ট্রান্সলেট (রূপান্তর, চিত্র.সাইজ.উইথথ, 0);
            রূপান্তর = সিজিএফাইন ট্রান্সফর্মস্কেল (রূপান্তর, -1, 1);
            বিরতি;

        কেস ইউআইআইজিওরিয়েন্টেশন লেফট মিররড:
        কেসআইআইআইজিএইজ ওরিয়েন্টেশন
            রূপান্তর = সিজিএফাইন ট্রান্সফর্ম ট্রান্সলেট (রূপান্তর, চিত্র.সাইজ.হাইট, 0);
            রূপান্তর = সিজিএফাইন ট্রান্সফর্মস্কেল (রূপান্তর, -1, 1);
            বিরতি;
        কেস ইউআইজিএজ ওরিয়েন্টেশনআপ:
        কেস ইউআইজিমেজ ওরিয়েন্টেশন ডাউন:
        কেস ইউআইজিমেজ ওরিয়েন্টেশন লেফট:
        কেসআইআইআইজিএজ ওরিয়েন্টেশন রাইট:
            বিরতি;
    }

    // এখন আমরা অন্তর্নিহিত সিজিআইমেজটিকে একটি নতুন প্রসঙ্গে রূপান্তর করব, রূপান্তরটি প্রয়োগ করছি
    // উপরে গণনা করা।
    CGContextRef ctx = CGBitmapContextCreate (NULL, image.size.width, image.size.height,
            সিজিআইমেজগেটবিটস পারকোম্পোনেন্ট (ইমেজ.সিজিআইমেজ), 0,
            CGImageGetColorSpace (image.CGImage),
            CGImageGetBitmapInfo (image.CGImage));
    CGContextConcatCTM (ctx, transform);
    স্যুইচ (image.imageOrientation) {
        কেস ইউআইজিমেজ ওরিয়েন্টেশন লেফট:
        কেস ইউআইআইজিওরিয়েন্টেশন লেফট মিররড:
        কেসআইআইআইজিএজ ওরিয়েন্টেশন রাইট:
        কেসআইআইআইজিএইজ ওরিয়েন্টেশন
            // গ্রার ...
            সিজি কনটেক্সটড্রাইজিমেজ (সিটিএক্স, সিজিআরেক্টমেক (0, 0, ইমেজ.সাইজ.হাইট, ইমেজ.সাইজ.উইথ), ইমেজ.সিজিআইজেশন);
            বিরতি;

        ডিফল্ট:
            সিজি কনটেক্সটড্রাইজিমেজ (সিটিএক্স, সিজিআরেক্টমেক (0, 0, ইমেজ.সাইজ.উইথ, ইমেজ.সাইজ.হাইট), ইমেজ.সিজিআইজেশন);
            বিরতি;
    }

    // এবং এখন আমরা অঙ্কন প্রসঙ্গে একটি নতুন ইউআইআইমেজ তৈরি করেছি
    সিজিআইমেজআরএফ সিজিিমগ = সিজিবিটম্যাপকন্টেক্সটক্রিয়াটেমেজ (সিটিএক্স);
    ইউআইআইমেজ * ইমজি = [ইউআইআইমেজ ইমেজ উইথসিজিআইমেজ: সিজিআইএমজি];
    CGContextRelease (CTX);
    CGImageRelease (cgimg);
    প্রত্যাবর্তন img;

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.