আইওএস ইমেজ ওরিয়েন্টেশন অদ্ভুত আচরণ আছে


95

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

আমার প্রশ্ন এখন কেন এমন হচ্ছে ? অ্যাপল কেন ঘোরানো চিত্র? আমি যখন আমার ক্যামেরার সাথে ডান দিকের উপরে কোনও ফটো তুলি, যদি না আমি উপরে উল্লিখিত আমার কোডটি সম্পাদন করি, যখন আমি ফটোটি সংরক্ষণ করি তখন এটি ঘোরানো হয়। এখন, আমার কর্মসংস্থান কিছুদিন আগে পর্যন্ত ঠিক ছিল।

আমার অ্যাপ্লিকেশনটি একটি চিত্রের পৃথক পিক্সেল, বিশেষত একটি পিএনজির আলফা চ্যানেল সংশোধন করে (যাতে কোনও জেপিইজি রূপান্তর আমার দৃশ্যের জন্য উইন্ডো থেকে ছিটকে যায়)। কিছু দিন আগে আমি লক্ষ্য করেছি যে চিত্রটি আমার কার্যতালিকা কোডের জন্য আমার অ্যাপ্লিকেশনটিতে সঠিকভাবে প্রদর্শিত হয়েছে, যখন আমার অ্যালগোরিদম চিত্রের পৃথক পিক্সেলকে সংশোধন করে, মনে হয় চিত্রটি ঘোরানো হয়েছে। সুতরাং চিত্রের শীর্ষে পিক্সেলগুলি পরিবর্তনের পরিবর্তে এটি চিত্রের পাশের পিক্সেলগুলি সংশোধন করে (কারণ এটি মনে করে যে এটি ঘোরানো উচিত)! মেমরিটিতে কীভাবে চিত্রটি ঘোরানো যায় তা আমি বুঝতে পারি না - আদর্শভাবে আমি কেবল imageOrientationসমস্ত পতাকা একসাথে মুছতে পছন্দ করব would

এখানে অন্য কিছু যা আমাকেও বিস্মিত করে চলেছে ... আমি যখন ছবি তুলি, তখন imageOrientationসেটি 3 এ সেট করা থাকে My আমার কাজের কোডটি এটি উপলব্ধি করার জন্য যথেষ্ট স্মার্ট এবং এটি ফ্লিপ করে যাতে ব্যবহারকারী কখনও খেয়াল করে না। তদ্ব্যতীত, লাইব্রেরিতে চিত্রটি সংরক্ষণ করার জন্য আমার কোড এটিকে উপলব্ধি করে, এটিকে ফ্লিপ করে, তারপরে এটি সংরক্ষণ করে যাতে এটি ক্যামেরার রোলটিতে সঠিকভাবে উপস্থিত হয়।

কোডটি দেখতে তেমন দেখাচ্ছে:

NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap 
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];   
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

আমি যখন এই নতুন সংরক্ষিত চিত্রটি আমার অ্যাপ্লিকেশনটিতে লোড করি তখন imageOrientationতা 0 - আমি দেখতে চাই ঠিক তাই হয়, এবং আমার ঘূর্ণনের কাজটি চালানোর প্রয়োজনও হয় না (দ্রষ্টব্য: কোনও ক্যামেরায় তোলা চিত্রের বিপরীতে ইন্টারনেট থেকে চিত্রগুলি লোড করার সময়) , imageOrientationসর্বদা 0 হয়, নিখুঁত আচরণের ফলে)। কোনও কারণে, আমার সংরক্ষণ কোডটি এই imageOrientationপতাকাটি মুছে ফেলবে বলে মনে হচ্ছে । আমি কেবল সেই কোডটি চুরি করে ব্যবহারকারীর ছবি নেওয়ার সাথে সাথে ছবিটি ওরিয়েন্টেশনটি মুছে ফেলার জন্য এটি ব্যবহার করার আশা করছিলাম এবং অ্যাপটিতে এটি যুক্ত হয়েছে, তবে এটি কার্যকর হবে বলে মনে হচ্ছে না। এর UIImageWriteToSavedPhotosAlbumসাথে বিশেষ কিছু করে imageOrientation?

এই সমস্যাটির সর্বোত্তম সমাধান imageOrientationহ'ল ব্যবহারকারী কোনও চিত্র নেওয়ার সাথে সাথেই এটি উড়িয়ে দেবে । আমি ধরে নিই অ্যাপল কোনও কারণে আবর্তন আচরণ করেছে, তাইনা? কিছু লোক পরামর্শ দিয়েছিলেন যে এটি একটি অ্যাপল ত্রুটি।

(... আপনি যদি এখনও হারিয়ে না যান ... দ্রষ্টব্য 2: আমি যখন একটি অনুভূমিক ছবি তুলি তখন ইন্টারনেট থেকে তোলা ফটোগুলির মতোই সবকিছু ঠিকঠাকভাবে কাজ করে বলে মনে হয়)

সম্পাদনা:

এখানে কিছু চিত্র এবং পরিস্থিতি বাস্তবে দেখতে কেমন। এখনও অবধি মন্তব্যগুলির ভিত্তিতে, দেখে মনে হচ্ছে এই অদ্ভুত আচরণটি কেবল আইফোনের আচরণের চেয়ে বেশি, যা আমি ভাল বলে মনে করি।

এটি আমার ফোনের সাথে তোলা ছবির একটি চিত্র (যথাযথ ওরিয়েন্টেশনটি নোট করুন), আমি যখন ছবিটি ছড়িয়ে দিয়েছিলাম তখন এটি আমার ফোনে যেমন হয়েছিল তেমন প্রদর্শিত হয়:

আইফোনে তোলা আসল ছবি

আমি নিজের কাছে ইমেল করার পরে চিত্রটি জিমেইলে দেখতে কেমন তা মনে হচ্ছে (মনে হয় জিমেইল এটি সঠিকভাবে পরিচালনা করে):

Gmail এ প্রদর্শিত হিসাবে ছবি

উইন্ডোতে চিত্রটি থাম্বনেইলের মতো দেখতে যা এখানে দেওয়া হচ্ছে (এটি সঠিকভাবে পরিচালনা করা হয় এমনটি মনে হয় না):

উইন্ডোজ থাম্বনেল

উইন্ডোজ ফটো ভিউয়ার দিয়ে খোলার সময় এখানে আসল চিত্রটি দেখতে কেমন তা দেখায় (এখনও সঠিকভাবে পরিচালনা করা হয় না):

উইন্ডোজ ফটো ভিউয়ার সংস্করণ

এই প্রশ্নের সমস্ত মন্তব্যের পরে, আমি যা ভাবছি তা এখানে ... আইফোন একটি চিত্র নিয়েছে এবং বলেছে "এটিকে সঠিকভাবে প্রদর্শন করতে এটি 90 ডিগ্রি ঘোরানো দরকার"। এই তথ্যটি এক্সইফের ডেটাতে থাকবে। (কেন এটিকে 90 ডিগ্রি ঘোরানো দরকার, সোজা উল্লম্বে ডিফল্ট করার পরিবর্তে, আমি জানি না)। এখান থেকে, জিএমএল সেই এক্সআইএফ ডেটাটি পড়তে এবং বিশ্লেষণ করতে এবং এটি সঠিকভাবে প্রদর্শন করার জন্য যথেষ্ট স্মার্ট। উইন্ডোজ অবশ্য এক্সআইএফ ডেটা পড়ার পক্ষে যথেষ্ট স্মার্ট নয় এবং তাই চিত্রটিকে ভুলভাবে প্রদর্শন করে । আমার অনুমানগুলি কি সঠিক?


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

দেখুন আপনার ক্যামেরা 90 ডিগ্রীতে এটিকে ঘোরানোর জন্য মেটাডেটা লিখেছেন, কিছু ওএস পড়েন যে মেটাডেটা এবং বিশ্রাম না।
হর্ষিত

খুব ভাল পড়া (নীচে @ হ্যাডলির উত্তর দেখুন - একটি মন্তব্যে ব্যবহৃত হত)। সুতরাং আমার অ্যাপ্লিকেশনটিতে স্পষ্টভাবে যথেষ্ট স্মার্ট হওয়া দরকার যেগুলি EXIF ​​ডেটাযুক্ত চিত্রগুলি হ্যান্ডেল করার জন্য, পাশাপাশি এটিতে থাকা চিত্রগুলিও রাখে না ... আমি এখনও বুঝতে পারি না কেন আমি যখন কোনও ফটো ডানদিকের দিকে উপরে তুলি, তখন ওরিয়েন্টেশন পতাকা এটি 90 ডিগ্রি ঘোরানো উচিত বলে?
বোকেকেম

আপনি নিজের ফটো মোডকে প্রতিকৃতিতে সেট করেছেন এবং আপনি আপনার ক্যামেরাটি ডান কোণে ঘোরছেন না বা ল্যান্ডস্কেপ মোড সেট করা হয়েছে এবং ক্যামেরাটি ডান কোণায়িত অবস্থায় ধারণ করেছে, সেন্সরটি স্বয়ংক্রিয়ভাবে ওরিয়েন্টেশনটিকে সঠিকভাবে সেট করবে। এটি দেখুন
হার্শিত

4
সলিউশনটি সম্ভবতঃ আপনার অ্যাপ্লিকেশনটির মেটা ডেটা পড়তে হবে এবং চিত্রটি ঘোরানো উচিত এবং / অথবা প্রয়োজনীয়তা অনুযায়ী মেটাডেটা পরিবর্তন করতে হবে।
হর্ষিত

উত্তর:


50

আমি এটিতে গবেষণা ও গবেষণা করেছি এবং আবিষ্কার করেছি, প্রতিটি চিত্রের ফাইলে মেটাডেটার সম্পত্তি থাকে। যদি মেটাডেটা চিত্রটির ওরিয়েন্টেশন নির্দিষ্ট করে তবে সাধারণত অন্য ওএস কিন্তু ম্যাক দ্বারা উপেক্ষা করা হয়। তোলা বেশিরভাগ ছবিতে তাদের মেটা ডেটা সম্পত্তিটি ডান কোণে সেট করা থাকে। সুতরাং ম্যাক এটি 90 ডিগ্রি ঘোরানো পদ্ধতিতে দেখায়। উইন্ডোজ ওএসে আপনি একই চিত্রটি সঠিক উপায়ে দেখতে পাবেন।

আরও বিশদের জন্য এই উত্তরটি পড়ুন: http://braicicoft.about.com/od/digitalphotography/f/sideways-pictures.htm

এখানে আপনার চিত্রের Exif পড়া চেষ্টা http://www.exifviewer.org/ , অথবা http://regex.info/exif.cgi , অথবা http://www.addictivetips.com/internet-tips/view-complete-exif -মেপাডাটা-যে-কোনও-জেপিগ-চিত্র-অনলাইন-এর তথ্য /


4
কি দারুন! এক্সআইএফ ডেটাতে আমার যে তথ্য রয়েছে তা আমার ধারণা ছিল না! regex.info/exif.cgi একটি অবিশ্বাস্য সাইট! আমি অবশ্যই আজ রাতে এই সাইটে ছবিগুলি নিয়ে ঘুরে দেখব। আমাকে প্রতিটি দৃশ্যের পরীক্ষা করতে হবে, চিত্রগুলি সরাসরি উপরে নেওয়া হবে, ইন্টারনেট থেকে তোলা ছবিগুলি, চিত্রগুলি ঘোরানো হয়েছে ইত্যাদি ইত্যাদি ধন্যবাদ একটি টন!
বোকেকেম

প্রথম এক্সিফ লিঙ্কটি এখন ভেঙে গেছে এবং দ্বিতীয়টি exif.regex.info/exif.cgi এ আপডেট করা হয়েছে আমি উত্তরটি সম্পাদনা করার চেষ্টা করেছি কিন্তু @ সিজে-ডেনিস কোনও কারণে এটি প্রত্যাখ্যান করেছে।
রায়ান

55

আমি যখন ক্যামেরা থেকে চিত্রটি পেয়েছিলাম তখন একই সমস্যা ছিলাম, আমি এটি ঠিক করার জন্য নিম্নলিখিত কোডটি রেখেছিলাম .. এখান থেকে পদ্ধতি স্কেলএন্ডআরোটেটআইমেজ যুক্ত করেছি

- (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo {
            // Images from the camera are always in landscape, so rotate
                    UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
    //then save the image to photo gallery or wherever  
        }


- (UIImage *)scaleAndRotateImage:(UIImage *) image {
    int kMaxResolution = 320;

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);


    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

4
আপনার স্কেলএন্ডআরোটেটএমেজ কোডটি দেখতে কেমন? গুগল করার পরে, এখানে কি একই রকম? আলোচনা.
apple.com/thread/1537011?start=0&tstart=0

4
বাহ ... হা হা! এটি অত্যন্ত ভাল কাজ করেছে! আমি উপরের আমার মন্তব্যে কোডটি ব্যবহার করেছি। আমি আমার প্রশ্নের দুটি আশ্চর্যজনক উত্তর পেয়েছি! আমার মনে হয় এর অর্থ আমি খুব বড় একটি প্রশ্ন জিজ্ঞাসা করেছি ... ধন্যবাদ একটি টন আমার কিছু করার জন্য গভীরতা পরীক্ষা করতে হবে, তবে এখনও পর্যন্ত উল্লম্ব এবং অনুভূমিকভাবে তোলা ফটোগুলি দিয়ে ওরিয়েন্টেশন সমস্যাটি দুর্দান্ত কাজ করে।
বোকেকেম

4
আমি মনে করি আপনার পদ্ধতিটির একটি অংশ অনুপস্থিত রয়েছে, তবে বাকি অংশটি কাজ করার জন্য এবং লিঙ্কটি এখনও যথেষ্ট ছিল আমার অবশেষে আমার চিত্রের ক্রপিং ভিউটি সঠিকভাবে কাজ করার জন্য, তাই ধন্যবাদ :)
ভিক স্মিথ

আমি আনন্দিত যে এটি সাহায্য করেছে .. :)
দিলীপ রাজকুমার

এই কোডটি কী ব্লকটি মূল চিত্রটি দেখতে দেখতে সংরক্ষণ করে তবে ওরিয়েন্টেশনটি আপকে বদলে দেয়?
জুনচাও গু

20

আমার প্রশ্ন এখন কেন এমন হচ্ছে? অ্যাপল কেন ঘোরানো চিত্র?

এর উত্তর খুব সহজ। অ্যাপল চিত্রটি ঘোরছে না। এখানেই বিভ্রান্তি রয়েছে।

সিসিডি ক্যামেরাটি ঘোরান না, তাই এটি সর্বদা ল্যান্ডস্কেপ মোডে ফটো তোলা হয়।

অ্যাপল একটি খুব স্মার্ট কাজ করেছে - চিত্রটি ঘোরানোর জন্য সমস্ত সময় ব্যয় করার পরিবর্তে - চারপাশে ডেটা মেগাবাইট বদলানো - কেবল ছবিটি কীভাবে তোলা হয়েছিল তা দিয়ে ট্যাগ করুন।

ওপেনজিএল অনুবাদ খুব সহজেই করে - তাই ডেটা কখনই বদলে যায় না - কেবল এটি কীভাবে ড্র হয়।

অতএব ওরিয়েন্টেশন মেটা ডেটা।

আপনি ক্রপ করতে চান, আকার পরিবর্তন করুন ইত্যাদি যদি এটি সমস্যা হয়ে যায় - তবে একবার আপনি কী হয়ে যাচ্ছেন তা জানতে পেরে আপনি কেবল নিজের ম্যাট্রিক্সটি সংজ্ঞায়িত করেন এবং সবকিছু কার্যকর হয়ে যায়।


4
এই ব্যাখ্যার জন্য আপনাকে ধন্যবাদ। সাধারণ জ্ঞান একবার আপনি এটি সম্পর্কে চিন্তা করে, কিন্তু অন্য কোন গুগল ফলাফল এটি ব্যাখ্যা।
ডাকাইন 83

একজন অধ্যাপকের মত সুন্দর ব্যাখ্যা। ধন্যবাদ!
vkGunasekaran

18

দিলীপের দুর্দান্ত উত্তরের দ্রুত কপি / পেস্ট সুইফট অনুবাদ ।

import Darwin

class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {

    let imgRef = imageSource.CGImage;

    let width = CGFloat(CGImageGetWidth(imgRef));
    let height = CGFloat(CGImageGetHeight(imgRef));

    var bounds = CGRectMake(0, 0, width, height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransformIdentity
    let orient = imageSource.imageOrientation
    let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef)))


    switch(imageSource.imageOrientation) {
    case .Up :
        transform = CGAffineTransformIdentity

    case .UpMirrored :
        transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);

    case .Down :
        transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI));

    case .DownMirrored :
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);

    case .Left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .LeftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .Right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    case .RightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    default : ()
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .Right || orient == .Left {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    } else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

4
ধন্যবাদ, তবে "লেট রেশিও = প্রস্থ / উচ্চতা;" ব্যবহার করছি? আমি সেই in in তে অনুপাত ব্যবহার করে কোনও জায়গা দেখতে পাচ্ছি না
Pengzhi Zhou

16

দিলীপের উত্তরের সুরক্ষা চেক সহ সুইফট 4 সংস্করণ ।

public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {

    guard let imgRef = imageSource.cgImage else {
        return nil
    }

    let width = CGFloat(imgRef.width)
    let height = CGFloat(imgRef.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))

    switch(imageSource.imageOrientation) {
    case .up:
        transform = .identity
    case .upMirrored:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: 0)
            .scaledBy(x: -1.0, y: 1.0)
    case .down:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: imageSize.height)
            .rotated(by: CGFloat.pi)
    case .downMirrored:
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.height)
            .scaledBy(x: 1.0, y: -1.0)
    case .left:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.width)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .leftMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: imageSize.width)
            .scaledBy(x: -1.0, y: 1.0)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: 0)
            .rotated(by: CGFloat.pi / 2.0)
    case .rightMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(scaleX: -1.0, y: 1.0)
            .rotated(by: CGFloat.pi / 2.0)
    }

    UIGraphicsBeginImageContext(bounds.size)
    if let context = UIGraphicsGetCurrentContext() {
        if orient == .right || orient == .left {
            context.scaleBy(x: -scaleRatio, y: scaleRatio)
            context.translateBy(x: -height, y: 0)
        } else {
            context.scaleBy(x: scaleRatio, y: -scaleRatio)
            context.translateBy(x: 0, y: -height)
        }

        context.concatenate(transform)
        context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
    }

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy
}

আপনি (bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)স্টোরেজ হিসাবে পরিবর্তনশীল তৈরি না করেও করতে পারেন ।
আলমাস সাপর্গালি

আমার মাঝে মাঝে সমস্যা ছিল যে, স্কেল করার পরে চিত্রের নীচে একটি সাদা লাইন উপস্থিত হয়েছিল। এটি কারণ সিজিফ্লোট যথেষ্ট সুনির্দিষ্ট নয় বলে মনে হচ্ছে। আমি এটি ঠিক bounds.size.height.round()এবংbounds.size.width.round()
ndreisg

13

আইফোন / আইপ্যাড দ্বারা উত্পন্ন যে কোনও চিত্র ল্যান্ডস্কেপ বাম হিসাবে EXIF ​​ওরিয়েন্টেশন ট্যাগ (Exif.Image.Orientation) সহ সংরক্ষিত হয় প্রকৃত ওরিয়েন্টেশন নির্দিষ্ট করে।

এটির নিম্নলিখিত মান রয়েছে: 1: ল্যান্ডস্কেপ বাম 6: প্রতিকৃতি সাধারণ 3: ল্যান্ডস্কেপ ডান 4: প্রতিকৃতি নীচে

আইওএস-এ, এক্সআইএফ তথ্যটি যথাযথভাবে পঠিত হয় এবং চিত্রগুলি যেভাবে নেওয়া হয়েছিল সেভাবে প্রদর্শিত হয়। তবে উইন্ডোজে, এক্সআইএফ তথ্য ব্যবহার করা হয় না।

আপনি যদি জিএমপিতে এই চিত্রগুলির মধ্যে একটি খুলেন, তবে এটির বলবে যে চিত্রটির ঘূর্ণন সম্পর্কিত তথ্য রয়েছে।


8

জামারিন ব্যবহার করে অন্য যে কোনও ব্যক্তির জন্য, এখানে দিলীপের দুর্দান্ত উত্তরের একটি সি # অনুবাদ রয়েছে এবং সুইফ্ট অনুবাদটির জন্য থ্যাটিসনকে ধন্যবাদ ।

public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) {

    var imgRef = imageSource.CGImage;

    var width = (nfloat)imgRef.Width;
    var height = (nfloat)imgRef.Height;

    var bounds = new CGRect(0, 0, width, height);

    nfloat scaleRatio = 1;

    if (width > maxResolution || height > maxResolution) 
    {
        scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
        bounds.Height = bounds.Height * scaleRatio;
        bounds.Width = bounds.Width * scaleRatio;
    }

    var transform = CGAffineTransform.MakeIdentity();
    var orient = imageSource.Orientation;
    var imageSize = new CGSize(imgRef.Width, imgRef.Height);
    nfloat storedHeight;

    switch(imageSource.Orientation) {
        case UIImageOrientation.Up:
            transform = CGAffineTransform.MakeIdentity();
            break;

        case UIImageOrientation.UpMirrored :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            break;

        case UIImageOrientation.Down :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
            break;

        case UIImageOrientation.DownMirrored :
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
            transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
            break;

        case UIImageOrientation.Left:
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.LeftMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.Right :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.RightMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        default :
            break;
    }

    UIGraphics.BeginImageContext(bounds.Size);
    var context = UIGraphics.GetCurrentContext();

    if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
        context.ScaleCTM(-scaleRatio, scaleRatio);
        context.TranslateCTM(-height, 0);
    } else {
        context.ScaleCTM(scaleRatio, -scaleRatio);
        context.TranslateCTM(0, -height);
    }

    context.ConcatCTM(transform);
    context.DrawImage(new CGRect(0, 0, width, height), imgRef);

    var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();

    return imageCopy;
}

এটি এই নিয়ে বেশ কয়েক ঘন্টা ব্যয় করার পরে আমার সমস্যার সমাধান করতে সহায়তা করেছে! অবিশ্বাস্য যে জ্যামারিনের এটির জন্য এখন কোনও মাইক্রোসফ্ট পণ্য হিসাবে দেওয়া কিছুটির জন্য অন্তর্নির্মিত সমর্থন নেই।
সামি.সি

4

আমি এই প্রশ্নটি পেরিয়ে এসেছি কারণ আমার একইরকম সমস্যা হচ্ছে, তবে সুইফ্টটি ব্যবহার করছি। অন্য যে কোনও সুইফট বিকাশকারীদের জন্য আমার পক্ষে কাজ করা উত্তরের সাথে কেবল লিঙ্কটি চেয়েছিলেন: https://stackoverflow.com/a/26676578/3904581

এখানে একটি সুইফট স্নিপেট রয়েছে যা দক্ষতার সাথে সমস্যার সমাধান করে:

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!

সুপার সিম্পল কোডের একটি লাইন। সমস্যা সমাধান.


এটি আমার পক্ষে কাজ করে না, আমি এই সমাধানটি ব্যবহার করেছি: stackoverflow.com/a/27775741/945247
লিওন

0

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


0

সুইফট 3 এর জন্য দ্রুত রিফ্যাক্টর (কেউ কি এটি পরীক্ষা করে প্রমাণ করতে পারে যে সবকিছু ঠিকঠাক কাজ করে?):

static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage

    let width = CGFloat(imgRef!.width)
    let height = CGFloat(imgRef!.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if width > maxResolution || height > maxResolution {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: imgRef!.width, height: imgRef!.height)

    switch imageSource.imageOrientation {
    case .up :
        transform = CGAffineTransform.identity

    case .upMirrored :
        transform = CGAffineTransform(translationX: imageSize.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

    case .down :
        transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height)
        transform = transform.rotated(by: CGFloat.pi)

    case .downMirrored :
        transform = CGAffineTransform(translationX: 0, y: imageSize.height)
        transform = transform.scaledBy(x: 1, y: -1)

    case .left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: 0, y: imageSize.width)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .leftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width)
        transform = transform.scaledBy(x: -1, y: 1)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: 0)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    case .rightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(scaleX: -1, y: 1)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .right || orient == .left {

        context!.scaleBy(x: -scaleRatio, y: scaleRatio)
        context!.translateBy(x: -height, y: 0)
    } else {
        context!.scaleBy(x: scaleRatio, y: -scaleRatio)
        context!.translateBy(x: 0, y: -height)
    }

    context!.concatenate(transform)
    context!.draw(imgRef!, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy!
}

0

দিলীপের দুর্দান্ত উত্তরটির সুইফট 3 সংস্করণটি এখানে

func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage!;

    let width = CGFloat(imgRef.width);
    let height = CGFloat(imgRef.height);

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {
        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: width, height: height)


    switch(imageSource.imageOrientation) {
        case .up :
            transform = CGAffineTransform.identity

        case .upMirrored :
            transform = CGAffineTransform(translationX: imageSize.width, y: 0.0);
            transform = transform.scaledBy(x: -1, y: 1);

        case .down :
            transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height);
            transform = transform.rotated(by: CGFloat(Double.pi));

        case .downMirrored :
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.height);
            transform = transform.scaledBy(x: 1, y: -1);

        case .left :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.width);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .leftMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width);
            transform = transform.scaledBy(x: -1, y: 1);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .right :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: 0.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);

        case .rightMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(scaleX: -1.0, y: 1.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()!

    if orient == .right || orient == .left {
        context.scaleBy(x: -scaleRatio, y: scaleRatio);
        context.translateBy(x: -height, y: 0);
    } else {
        context.scaleBy(x: scaleRatio, y: -scaleRatio);
        context.translateBy(x: 0, y: -height);
    }

    context.concatenate(transform);
    context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy!;
}

-3

ইমেজ ফর্ম্যাটটি .jpeg এ পরিবর্তন করার চেষ্টা করুন। এটি আমার পক্ষে কাজ করেছে

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