2012-06-27 4 views
8

मैं आईफोन पर इंस्टाग्राम जैसे कुछ छवि फ़िल्टर सुविधाओं को आजमा देना चाहता हूं। मैं कैमरे रोल से फोटो प्राप्त करने के लिए imagePickerController का उपयोग करता हूं। मैं समझता हूं कि छवि PicerController द्वारा छवि वापसी स्मृति को बचाने के लिए कम कर दिया गया था। और मूल छवि को UIImage में लोड करना बुद्धिमान नहीं है। लेकिन मैं छवि को कैसे संसाधित कर सकता हूं और इसे मूल पिक्सेल के रूप में वापस सहेज सकता हूं? मैं अपने विकास उपकरण के रूप में आईफोन 4 एस का उपयोग करता हूं।कैमरा रोल में फोटो में स्क्वायर कट कैसे करें?

कैमरा रोल में मूल तस्वीर है 3264 * 2448.

UIImagePickerControllerOriginalImage द्वारा छवि वापसी 1920 * 1440 है

UIImagePickerControllerEditedImage द्वारा छवि वापसी 640 * 640

imageViewOld (UIImagePickerControllerCropRect [का उपयोग करें 80,216,1280,1280] UIImagePickerControllerOriginalImage द्वारा छवि वापसी कांट-छांट करना) 1280 * 1224

imageViewNew (का उपयोग डबल आकार UIImagePickerControll है erCropRect [80,216,2560,2560] UIImagePickerControllerOriginalImage द्वारा छवि वापसी कांट-छांट करना) 1840 * 1224.

मैं एक ही तस्वीर देखने के instagram से आगे बढ़ना है 1280 * 1280

मेरे सवाल कर रहे हैं है:

  1. क्यों UIImagePickerControllerOriginalImage "मूल" फ़ोटो वापस नहीं करता है? इसे 1920 * 1440 तक क्यों कम किया?
  2. क्यों UIImagePickerControllerEditedImage 1280 * 1280 तक छवि वापस नहीं करता है?
    UIImagePickerControllerCropRect दिखाता है कि यह 1280 * 1280 वर्ग द्वारा काटा गया है?

  3. मैं 2448 * 2448 छवि होने के लिए मूल तस्वीर में स्क्वायर कट कैसे कर सकता हूं?

अग्रिम धन्यवाद। नीचे मेरी कोड है:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
    { 

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 
    if ([mediaType isEqualToString:@"public.image"]) 
    { 

    UIImage *imageEdited = [info objectForKey:UIImagePickerControllerEditedImage]; 
    UIImage *imagePicked = [info objectForKey:UIImagePickerControllerOriginalImage]; 

    CGRect cropRect; 
    cropRect = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue]; 

    NSLog(@"Original width = %f height= %f ",imagePicked.size.width, imagePicked.size.height); 
    //Original width = 1440.000000 height= 1920.000000 

    NSLog(@"imageEdited width = %f height = %f",imageEdited.size.width, imageEdited.size.height); 
    //imageEdited width = 640.000000 height = 640.000000 

    NSLog(@"corpRect %f %f %f %f", cropRect.origin.x, cropRect.origin.y , cropRect.size.width, cropRect.size.height); 
    //corpRect 80.000000 216.000000 1280.000000 1280.000000 

    CGRect rectNew = CGRectMake(cropRect.origin.x, cropRect.origin.y , cropRect.size.width*2, cropRect.size.height*2); 

    CGRect rectOld = CGRectMake(cropRect.origin.x, cropRect.origin.y , cropRect.size.width, cropRect.size.height); 

    CGImageRef imageRefNew = CGImageCreateWithImageInRect([imagePicked CGImage], rectNew); 
    CGImageRef imageRefOld = CGImageCreateWithImageInRect([imagePicked CGImage], rectOld); 

    UIImageView *imageViewNew = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:imageRefNew]]; 
    CGImageRelease(imageRefNew); 

    UIImageView *imageViewOld = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:imageRefOld]]; 
    CGImageRelease(imageRefOld); 


    NSLog(@"imageViewNew width = %f height = %f",imageViewNew.image.size.width, imageViewNew.image.size.height); 
    //imageViewNew width = 1840.000000 height = 1224.000000 

    NSLog(@"imageViewOld width = %f height = %f",imageViewOld.image.size.width, imageViewOld.image.size.height); 
    //imageViewOld width = 1280.000000 height = 1224.000000 

    UIImageWriteToSavedPhotosAlbum(imageEdited, nil, nil, NULL); 

    UIImageWriteToSavedPhotosAlbum([imageViewNew.image imageRotatedByDegrees:90.0], nil, nil, NULL); 
    UIImageWriteToSavedPhotosAlbum([imageViewOld.image imageRotatedByDegrees:90.0], nil, nil, NULL); 


    //assign the image to an UIImage Control 
    self.imageV.contentMode = UIViewContentModeScaleAspectFit; 
    self.imageV.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width); 
    self.imageV.image = imageEdited; 


    } 

    [self dismissModalViewControllerAnimated:YES]; 

} 

उत्तर

12

आप देखा है UIImagePickerController कभी कभी 640x640 कभी कभी 320x320 (डिवाइस निर्भर) एक छोटा संपादित छवि वापस आ जाएगी के रूप में।

आपका प्रश्न:

मैं मूल फ़ोटो में एक स्क्वायर कट एक 2448 * 2448 छवि के लिए क्या कर सकते हैं कैसे?

इस आप पहली बार UIImagePickerControllerCropRect उपयोग करने के लिए जानकारी शब्दकोश की UIImagePickerControllerOriginalImage कुंजी का उपयोग कर प्राप्त मूल छवि से एक नई छवि बनाने की जरूरत करने के लिए। क्वार्ट्ज कोर विधि का उपयोग करके, CGImageCreateWithImageInRect आप एक नई छवि बना सकते हैं जिसमें केवल पारित आय से घिरे पिक्सेल शामिल हों; इस मामले में फसल आयत। ठीक से काम करने के लिए आपको खाता अभिविन्यास को ध्यान में रखना होगा। फिर आपको केवल वांछित आकार में छवि को स्केल करने की आवश्यकता है। यह ध्यान रखना महत्वपूर्ण है कि फसल रेक्ट मूल छवि के सापेक्ष है जब इसे ठीक से उन्मुख किया गया है, न कि यह कैमरा या फोटो लाइब्रेरी से बाहर आता है। यही कारण है कि जब हम नई छवियां बनाने के लिए क्वार्ट्ज विधियों का उपयोग शुरू करते हैं, तो हमें उन्मुखीकरण से मेल खाने के लिए फसल रेक्ट को बदलने की आवश्यकता होती है।

मैंने अपना कोड ऊपर ले लिया और इसे फसल आय के आधार पर मूल छवि से 1280x1280 छवि बनाने के लिए सेट अप किया। यहां अभी भी कुछ किनारे के मामले हैं, यानी ध्यान में रखते हुए कि फसल आयत में कभी-कभी नकारात्मक मूल्य हो सकते हैं, (कोड एक स्क्वायर क्रॉपिंग रेक्ट मानता है) जिसे संबोधित नहीं किया गया है।

  1. पहले आने वाली छवि और आकार के अभिविन्यास को ध्यान में रखने के लिए फसल आयत को परिवर्तित करें। यह transformCGRectForUIImageOrientation फ़ंक्शन NiftyBean
  2. एक छवि बनाएं जो परिवर्तित क्रॉपिंग रेक्ट में फसल हो।
  3. स्केल (और घुमाने) इच्छित आकार करने के लिए छवि। यानी 1280x1280।
  4. सही पैमाने पर और उन्मुखीकरण के साथ CGImage से एक UIImage बनाएँ। अद्यतन नए कोड इस नीचे जोड़ दिया गया है कि लापता मामलों का ध्यान रखना चाहिए:

यहां उन परिवर्तनों के साथ अपने कोड है।

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 
if ([mediaType isEqualToString:@"public.image"]) 
{ 

    UIImage *imageEdited = [info objectForKey:UIImagePickerControllerEditedImage]; 
    UIImage *imagePicked = [info objectForKey:UIImagePickerControllerOriginalImage]; 

    CGRect cropRect; 
    cropRect = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue]; 

    NSLog(@"Original width = %f height= %f ",imagePicked.size.width, imagePicked.size.height); 
    //Original width = 1440.000000 height= 1920.000000 

    NSLog(@"imageEdited width = %f height = %f",imageEdited.size.width, imageEdited.size.height); 
    //imageEdited width = 640.000000 height = 640.000000 

    NSLog(@"corpRect %@", NSStringFromCGRect(cropRect)); 
    //corpRect 80.000000 216.000000 1280.000000 1280.000000 

    CGSize finalSize = CGSizeMake(1280,1280); 
    CGImageRef imagePickedRef = imagePicked.CGImage; 

    CGRect transformedRect = transformCGRectForUIImageOrientation(cropRect, imagePicked.imageOrientation, imagePicked.size); 
    CGImageRef cropRectImage = CGImageCreateWithImageInRect(imagePickedRef, transformedRect); 
    CGColorSpaceRef colorspace = CGImageGetColorSpace(imagePickedRef); 
    CGContextRef context = CGBitmapContextCreate(NULL, 
               finalSize.width, 
               finalSize.height, 
               CGImageGetBitsPerComponent(imagePickedRef), 
               CGImageGetBytesPerRow(imagePickedRef), 
               colorspace, 
               CGImageGetAlphaInfo(imagePickedRef)); 
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh); //Give the context a hint that we want high quality during the scale 
    CGContextDrawImage(context, CGRectMake(0, 0, finalSize.width, finalSize.height), cropRectImage); 
    CGImageRelease(cropRectImage); 

    CGImageRef instaImage = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 

    //assign the image to an UIImage Control 
    UIImage *image = [UIImage imageWithCGImage:instaImage scale:imagePicked.scale orientation:imagePicked.imageOrientation]; 
    self.imageView.contentMode = UIViewContentModeScaleAspectFit; 
    self.imageView.image = image; 
    CGImageRelease(instaImage); 

    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 
} 

[self dismissModalViewControllerAnimated:YES]; 

}

CGRect transformCGRectForUIImageOrientation(CGRect source, UIImageOrientation orientation, CGSize imageSize) { 
switch (orientation) { 
    case UIImageOrientationLeft: { // EXIF #8 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2); 
     return CGRectApplyAffineTransform(source, txCompound); 
    } 
    case UIImageOrientationDown: { // EXIF #3 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI); 
     return CGRectApplyAffineTransform(source, txCompound); 
    } 
    case UIImageOrientationRight: { // EXIF #6 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI + M_PI_2); 
     return CGRectApplyAffineTransform(source, txCompound); 
    } 
    case UIImageOrientationUp: // EXIF #1 - do nothing 
    default: // EXIF 2,4,5,7 - ignore 
     return source; 
} 
} 

अद्यतन मैं तरीकों कि मामलों की बाकी की देखभाल करेंगे की एक जोड़ी बना दिया है। कुछ संशोधन के साथ चरण मूल रूप से समान हैं।

  1. पहले संशोधन को सही ढंग से
  2. को बदलने और संदर्भ भेजे छवि के उन्मुखीकरण को संभालने के लिए पैमाने पर करने, और दूसरा गैर वर्ग फसलों आप UIImagePickerController से प्राप्त कर सकते हैं समर्थन करने के लिए है। इन मामलों में वर्ग छवि आपके चयन के रंग से भरा है।

नए कोड

// CropRect is assumed to be in UIImageOrientationUp, as it is delivered this way from the UIImagePickerController when using AllowsImageEditing is on. 
// The sourceImage can be in any orientation, the crop will be transformed to match 
// The output image bounds define the final size of the image, the image will be scaled to fit,(AspectFit) the bounds, the fill color will be 
// used for areas that are not covered by the scaled image. 
-(UIImage *)cropImage:(UIImage *)sourceImage cropRect:(CGRect)cropRect aspectFitBounds:(CGSize)finalImageSize fillColor:(UIColor *)fillColor { 

CGImageRef sourceImageRef = sourceImage.CGImage; 

//Since the crop rect is in UIImageOrientationUp we need to transform it to match the source image. 
CGAffineTransform rectTransform = [self transformSize:sourceImage.size orientation:sourceImage.imageOrientation]; 
CGRect transformedRect = CGRectApplyAffineTransform(cropRect, rectTransform); 

//Now we get just the region of the source image that we are interested in. 
CGImageRef cropRectImage = CGImageCreateWithImageInRect(sourceImageRef, transformedRect); 

//Figure out which dimension fits within our final size and calculate the aspect correct rect that will fit in our new bounds 
CGFloat horizontalRatio = finalImageSize.width/CGImageGetWidth(cropRectImage); 
CGFloat verticalRatio = finalImageSize.height/CGImageGetHeight(cropRectImage); 
CGFloat ratio = MIN(horizontalRatio, verticalRatio); //Aspect Fit 
CGSize aspectFitSize = CGSizeMake(CGImageGetWidth(cropRectImage) * ratio, CGImageGetHeight(cropRectImage) * ratio); 


CGContextRef context = CGBitmapContextCreate(NULL, 
              finalImageSize.width, 
              finalImageSize.height, 
              CGImageGetBitsPerComponent(cropRectImage), 
              0, 
              CGImageGetColorSpace(cropRectImage), 
              CGImageGetBitmapInfo(cropRectImage)); 

if (context == NULL) { 
    NSLog(@"NULL CONTEXT!"); 
} 

//Fill with our background color 
CGContextSetFillColorWithColor(context, fillColor.CGColor); 
CGContextFillRect(context, CGRectMake(0, 0, finalImageSize.width, finalImageSize.height)); 

//We need to rotate and transform the context based on the orientation of the source image. 
CGAffineTransform contextTransform = [self transformSize:finalImageSize orientation:sourceImage.imageOrientation]; 
CGContextConcatCTM(context, contextTransform); 

//Give the context a hint that we want high quality during the scale 
CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 

//Draw our image centered vertically and horizontally in our context. 
CGContextDrawImage(context, CGRectMake((finalImageSize.width-aspectFitSize.width)/2, (finalImageSize.height-aspectFitSize.height)/2, aspectFitSize.width, aspectFitSize.height), cropRectImage); 

//Start cleaning up.. 
CGImageRelease(cropRectImage); 

CGImageRef finalImageRef = CGBitmapContextCreateImage(context); 
UIImage *finalImage = [UIImage imageWithCGImage:finalImageRef]; 

CGContextRelease(context); 
CGImageRelease(finalImageRef); 
return finalImage; 
} 

//Creates a transform that will correctly rotate and translate for the passed orientation. 
//Based on code from niftyBean.com 
- (CGAffineTransform) transformSize:(CGSize)imageSize orientation:(UIImageOrientation)orientation { 

CGAffineTransform transform = CGAffineTransformIdentity; 
switch (orientation) { 
    case UIImageOrientationLeft: { // EXIF #8 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2); 
     transform = txCompound; 
     break; 
    } 
    case UIImageOrientationDown: { // EXIF #3 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI); 
     transform = txCompound; 
     break; 
    } 
    case UIImageOrientationRight: { // EXIF #6 
     CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width); 
     CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,-M_PI_2); 
     transform = txCompound; 
     break; 
    } 
    case UIImageOrientationUp: // EXIF #1 - do nothing 
    default: // EXIF 2,4,5,7 - ignore 
     break; 
} 
return transform; 

} 
+0

हाँ! यह वास्तव में कारगर है! क्या आप मुझे बता सकते हैं कि UIImagePickerController मुझे कैमरा रोल में मूल छवि क्यों नहीं देता है? – user1486413

+0

मुझे यकीन नहीं है कि इसके पीछे तर्क क्या है। मैंने देखा है कि कैमरे के साथ तस्वीर लेने पर आपको निश्चित रूप से एक पूर्ण रिज़ॉल्यूशन संस्करण मिलता है। आप पूर्ण संकल्प संस्करण प्राप्त करने की जरूरत है, मुझे लगता है कि आप इसे वापस 'ALAssetLibrary' वर्गों के साथ संयोजन में' UIImagePickerControllerReferenceURL' उपयोग कर सकते हैं। इस ढांचे का उपयोग करने से आपके उपयोगकर्ताओं को उनके स्थान तक पहुंचने की अनुमति के लिए कहा जाएगा, क्योंकि मूल छवियों को भू-टैग किया गया होगा। –

+0

भी .. अधिक sanely रोटेशन को संभालने के लिए कोड अद्यतन, और यह भी यहाँ तक कि एक वर्ग छवि हो रही हैंडल जब फसल रेक्ट वर्ग नहीं है। आशा करता हूँ की ये काम करेगा। –