2012-06-27 23 views
8

iPhone'da instagram gibi bazı görüntü filtresi özelliklerini denemek isterim. Fotoğraf makinesini rulodan almak için imagePickerController kullanıyorum. ImagePickerController tarafından döndürülen görüntünün belleği kurtarmak için azaltıldığını anlıyorum. Orijinal görüntüyü bir UIImage'a yüklemek akıllıca değildir. Ancak görüntüyü nasıl işleyebilirim ve orijinal piksel olarak nasıl kaydedebilirim? iPhone 4S'yi geliştirme cihazım olarak kullanıyorum.Fotoğraf makinesi rulosundaki kareler nasıl kesilir?

kamera rulo orijinal fotoğraftır 3264 * 2448.

UIImagePickerControllerOriginalImage görüntü dönüş * 1440 1920

UIImagePickerControllerEditedImage görüntü dönüş 640 * 640

imageViewOld (UIImagePickerControllerCropRect [kullanmaktır 80,216,1280,1280] görüntü dönüşünü UIImagePickerControllerOriginalImage ile kırpmak için) 1280 * 1224

imageViewNew (çift boyutlu UIImagePickerControll kullan) erCropRect [80,216,2560,2560]) UIImagePickerControllerOriginalImage görüntü dönüşünü kırpmak için 1840 * 1224.

Ben

Benim sorular * 1280 1280 olan bir instagram tarafından devam aynı fotoğraf kontrol etmektir:

  1. UIImagePickerControllerOriginalImage neden "Orijinal" fotoğrafı döndürmüyor? Neden 1920 * 1440'a düşürdü?
  2. Neden UIImagePickerControllerEditedImage, resmi 1280 * 1280 ile döndürmez?
    UIImagePickerControllerCropRect'in gösterdiği gibi 1280 * 1280 kare kesiliyor mu?

  3. 2448 * 2448 resmi olmak için orijinal fotoğrafa kare kesimi nasıl yapabilirim?

Şimdiden teşekkürler. Aşağıda benim kodudur:

Eğer UIImagePickerController bazen 640x640 bazen 320x320 (cihaz bağlı) bir küçültülmüş Düzenlenen resim döndürür de gözlemlediği gibi
- (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]; 

} 

cevap

12

.

Sorunuz:

Ben orijinal fotoğrafın bir kare kesilmiş bir 2448 * 2448 resim olarak da yapabiliriz nasıl

?

öncelikle bilgi sözlüğü UIImagePickerControllerOriginalImage anahtarı kullanılarak elde orijinal görüntüden yeni bir resim oluşturmak için UIImagePickerControllerCropRect kullanmak gerekir Bunu yapmak için. Quartz Core yöntemini kullanarak, CGImageCreateWithImageInRect, yalnızca geçen rect tarafından sınırlanmış olan pikselleri içeren yeni bir görüntü yaratabilirsiniz; bu durumda ürün rect. Bunun düzgün çalışması için yönlendirmeyi dikkate almanız gerekir. Ardından görüntüyü istediğiniz boyuta ayarlamanız yeterlidir. Fotoğraf makinesinden veya fotoğraf kitaplığından çıktığı gibi değil, doğru yönlendirildikten sonra kırpma rektinin orijinal görüntüye göre göründüğüne dikkat etmek önemlidir. Bu yüzden yeni görüntüleri, vb. Oluşturmak için Quartz yöntemlerini kullanmaya başladığımızda kırpma rektini yönelim ile eşleştirmeye ihtiyacımız var.

Yukarıda kodunuzu aldı ve mahsul rect'in dayalı orijinal resimden bir 1280x1280 görüntü oluşturmak için kurmak. Burada bazı kenar durumları söz konusudur, yani, mahsül rektinin bazen negatif değerlere sahip olduğunu (kodun bir kare kırpma rektini aldığını) göz önünde bulundurarak dikkate alınmamıştır.

  1. Önce gelen görüntü ve boyutun yönünü dikkate almak için kırpma rektini dönüştürün. NiftyBean
  2. dönüştürülmüş kırpma rect'in için kırpılmış bir görüntü oluşturun gelen bu transformCGRectForUIImageOrientation fonksiyonudur.
  3. Ölçeği (ve döndürme) istenen boyuta görüntü. 1280x1280.
  4. doğru ölçek ve oryantasyon ile CGImage bir UIImage oluşturun. Eksik durumlarda dikkatli olmalıdır Yeni kod aşağıda eklendi GÜNCELLEME:

İşte değişikliklerle sizin kodudur.

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

GÜNCELLEME Ben vakaların kalanı ilgilenir yöntemlerden birkaç yapmış. Adımlar, birkaç değişiklikle temel olarak aynıdır.

  1. ilk modifikasyon doğru
  2. dönüşümü ve gelen görüntü yönünü idare bağlam ölçeklemek ve ikinci Eğer UIImagePickerController alabilirsiniz kare olmayan bitkileri desteklemektir. Bu durumlarda kare görüntü seçeceğiniz bir renkle dolu 'dur.

Yeni Kod

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

Evet! Çalışıyor! UIImagePickerController'ın neden kamera rulosunda orijinal görüntüyü vermediğini söyler misiniz? – user1486413

+0

Akıl yürütmenin arkasında ne olduğundan emin değilim. Kamera ile fotoğraf çekerken kesinlikle tam çözünürlükte bir versiyon aldığınızı gözlemledim. Eğer tam çözünürlükte sürümü almak gerekiyorsa, bunu almak için 'ALAssetLibrary' sınıflarıyla birlikte' UIImagePickerControllerReferenceURL' kullanabiliriz. Bu çerçeveyi kullanmak, orijinal görseller coğrafi etiketli olacağından kullanıcılarınızın konumlarına erişme izni vermelerini ister. –

+0

Ayrıca .. daha sanely dönüşünü işlemek için kod güncellenir ve kırpma rect kare olmadığı zaman da bile kare görüntü elde kolları. Umarım yardımcı olur. –

İlgili konular