2013-07-26 6 views
14

मेरे ऐप में उपयोगकर्ता UIImagePickerViewController का उपयोग करके एक छवि चुनता है या एक तस्वीर लेता है। एक बार छवि का चयन करने के बाद मैं एक वर्ग UIImageView (90x90) पर अपना थंबनेल प्रदर्शित करना चाहता हूं।UIImagePickerViewController छवि से स्क्वायर थंबनेल छवि

मैं थंबनेल बनाने के लिए Apple's code का उपयोग कर रहा हूं। समस्या यह है कि थंबनेल वर्ग नहीं है, फ़ंक्शन, सेट केसीजीआईमेजसोर्स थंबनेल मैक्स पिक्सेल आकार कुंजी 9 0 के बाद, केवल छवि की ऊंचाई का आकार बदलने लगता है, और जहां तक ​​मुझे पता है कि केसीजीआईमेजसोर्स थंबनेलमैक्स पिक्सेल आकार कुंजी थंबनेल की ऊंचाई और चौड़ाई को सेट करने के लिए ज़िम्मेदार होना चाहिए।

यहाँ मेरी कोड की एक झलक है:

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

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; 

    NSData *imageData = UIImageJPEGRepresentation (image, 0.5); 

    // My image view is 90x90 
    UIImage *thumbImage = MyCreateThumbnailImageFromData(imageData, 90); 

    [myImageView setImage:thumbImage]; 

    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { 

     UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 
    } 

    [picker dismissViewControllerAnimated:YES completion:nil]; 
} 

UIImage* MyCreateThumbnailImageFromData (NSData * data, int imageSize) { 

    CGImageRef  myThumbnailImage = NULL; 
    CGImageSourceRef myImageSource; 
    CFDictionaryRef myOptions = NULL; 
    CFStringRef  myKeys[3]; 
    CFTypeRef   myValues[3]; 
    CFNumberRef  thumbnailSize; 

    // Create an image source from NSData; no options. 
    myImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, 
               NULL); 

    // Make sure the image source exists before continuing. 
    if (myImageSource == NULL){ 
     fprintf(stderr, "Image source is NULL."); 
     return NULL; 
    } 

    // Package the integer as a CFNumber object. Using CFTypes allows you 
    // to more easily create the options dictionary later. 
    thumbnailSize = CFNumberCreate(NULL, kCFNumberIntType, &imageSize); 

    // Set up the thumbnail options. 
    myKeys[0] = kCGImageSourceCreateThumbnailWithTransform; 
    myValues[0] = (CFTypeRef)kCFBooleanTrue; 
    myKeys[1] = kCGImageSourceCreateThumbnailFromImageIfAbsent; 
    myValues[1] = (CFTypeRef)kCFBooleanTrue; 
    myKeys[2] = kCGImageSourceThumbnailMaxPixelSize; 
    myValues[2] = thumbnailSize; 

    myOptions = CFDictionaryCreate(NULL, (const void **) myKeys, 
            (const void **) myValues, 2, 
            &kCFTypeDictionaryKeyCallBacks, 
            & kCFTypeDictionaryValueCallBacks); 

    // Create the thumbnail image using the specified options. 
    myThumbnailImage = CGImageSourceCreateThumbnailAtIndex(myImageSource, 
                  0, 
                  myOptions); 

    UIImage* scaled = [UIImage imageWithCGImage:myThumbnailImage]; 

    // Release the options dictionary and the image source 
    // when you no longer need them. 

    CFRelease(thumbnailSize); 
    CFRelease(myOptions); 
    CFRelease(myImageSource); 

    // Make sure the thumbnail image exists before continuing. 
    if (myThumbnailImage == NULL) { 
     fprintf(stderr, "Thumbnail image not created from image source."); 
     return NULL; 
    } 
    return scaled; 
} 

और यह कैसे मेरी छवि को देखने instantiated है:

myImageView = [[UIImageView alloc] init]; 
imageView.contentMode = UIViewContentModeScaleAspectFit; 

CGRect rect = imageView.frame; 
rect.size.height = 90; 
rect.size.width = 90; 

imageView.frame = rect; 
[imageView setUserInteractionEnabled:YES]; 

मैं imageView.contentMode = UIViewContentModeScaleAspectFit; निर्धारित नहीं करते हैं थम्बनेल, विकृत हो जाएगा के बाद से 90 पिक्सेल की ऊंचाई के साथ मेरी मूल छवि का सिर्फ एक संस्करण है।

तो, मेरा थंबनेल क्यों नहीं है?

1) UIImage+Resize

2) UIImage+ProportionalFill

यहाँ आप दृश्य का आकार बदलने के लिए और भी इतना है कि अनुपात में पहलू अनुपात और अन्य आनुपातिक भरण जोड़ सकते हैं:

+0

नोट - आईओएस का कोई ज्ञान के साथ एक मेटा उपयोगकर्ता दूर संपादित कुछ सुपर आसान कोड नीचे चालाक के जवाब से। यदि आप वास्तव में प्रोग्रामिंग कर रहे हैं और वास्तव में एक उपयोगी उत्तर चाहते हैं और वास्तव में चालावर (शानदार) विचारों का उपयोग करना चाहते हैं, तो बस नीचे दिए गए "संपादित" बटन पर क्लिक करें, आप इतिहास देखेंगे और ऐप स्टोर में कट, पेस्ट और भेज सकते हैं:) – Fattie

+0

@JoeBlow मुझे चालाक त्रुटि के उत्तर के [संपादित इतिहास] (http://stackoverflow.com/posts/17884863/revisions) में कोई भी हटाया गया कोड नहीं दिख रहा है। – cpburnz

+0

http://stackoverflow.com/posts/17884863/revisions rev "5" – Fattie

उत्तर

52

अपनी छवि पर contentMode सेट करना सबसे आसान बात यह है कि UIViewContentModeScaleAspectFill के बजाय देखें। हालांकि, यह आदर्श नहीं हो सकता है क्योंकि यह पूरी छवि को स्मृति में रखेगा।

यहां कुछ कोड है जिसका उपयोग मैं छवियों का आकार बदलने के लिए करता हूं।

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size 
{ 
    UIGraphicsBeginImageContextWithOptions(size, NO, 0); 
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 
    return newImage; 
} 

यह संस्करण छवि को विकृत होने से छवि को विकृत होने से रोक देगा यदि आकार छवि के समान अनुपात अनुपात नहीं है।

+ (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size 
{ 
    CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height); 
    CGFloat width = image.size.width * scale; 
    CGFloat height = image.size.height * scale; 
    CGRect imageRect = CGRectMake((size.width - width)/2.0f, 
            (size.height - height)/2.0f, 
            width, 
            height); 

    UIGraphicsBeginImageContextWithOptions(size, NO, 0); 
    [image drawInRect:imageRect]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 
    return newImage; 
} 

अक्सर आप (बल्कि केंद्र की तुलना में) एक छवि का सिर्फ शीर्ष वर्ग चाहते हैं। और आप चाहते हैं कि अंतिम छवि एक निश्चित आकार का हो, 128x128 कहें, जैसा कि नीचे दिए गए उदाहरण में है।

- (UIImage *)squareAndSmall // as a category (so, 'self' is the input image) 
{ 
    // fromCleverError's original 
    // http://stackoverflow.com/questions/17884555 
    CGSize finalsize = CGSizeMake(128,128); 

    CGFloat scale = MAX(
     finalsize.width/self.size.width, 
     finalsize.height/self.size.height); 
    CGFloat width = self.size.width * scale; 
    CGFloat height = self.size.height * scale; 

    CGRect rr = CGRectMake(0, 0, width, height); 

    UIGraphicsBeginImageContextWithOptions(finalsize, NO, 0); 
    [self drawInRect:rr]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 
    return newImage; 
} 
+0

यह दृष्टिकोण छवि विकृत करता है, मैंने पहले ही ऐसा कुछ करने की कोशिश की है। – douglasd3

+2

मैंने एक संस्करण जोड़ा जो छवि को विकृत नहीं करना चाहिए। –

+0

अब यह विकृत नहीं होता है, लेकिन थंबनेल छवि वर्ग नहीं है, मेरा मतलब है, यह 90x 9 0 है लेकिन छवि को वर्ग को भरने के लिए स्केल नहीं किया गया था। – douglasd3

6

यह लिंक है आप का उल्लेख कर सकते है फसल, स्केल इत्यादि जैसे कार्य

आप संदर्भ लिंक के तहत -(UIImage*)resizedImageToSize:(CGSize*)size विधि का उपयोग कर सकते हैं UIImage + छवि का आकार बदलने के लिए उपरोक्त आकार बदलें।

उम्मीद है कि यह आपकी मदद करता है।

अगर आपको और सहायता चाहिए तो मुझे बताएं।

+0

दूसरा लिंक वास्तव में सहायक था! मुझे अभी भी पता नहीं है कि समस्या क्या थी, लेकिन अब काम कर रहा है, और यह मुझे बहुत समय बचाएगा। धन्यवाद! – douglasd3

+1

@ douglasd3: दूसरा लिंक फसल और स्केलिंग जैसी कई सुविधाओं के लिए वास्तव में सहायक है। –

0

यह करने के लिए एक और तरीका है - दूसरे दिन एक मुद्दा में भाग और अन्य लोगों को एक ही मुद्दा है जब apple sample code जो बड़ी छवियों के लिए सबसे अच्छा है का उपयोग कर सकता है।

जैसा कि स्वीकृत उत्तर में बताया गया है, इसमें पूरी छवि को स्मृति में लोड करने की समस्या है और यदि यह बहुत बड़ा है तो आईओएस आपके ऐप को मार सकता है।AppleI उदाहरण सॉफ़्टवेयर में CGImageSourceCreateThumbnailAtIndex अधिक कुशल है, हालांकि उदाहरण में एक बग है। CFDictionaryCreate में तीसरा पैरामीटर कॉपी करने के लिए "numValues" है। होने की जरूरत है नहीं 2.

myOptions = CFDictionaryCreate(NULL, (const void **) myKeys, 
           (const void **) myValues, 
           3, //Changed to 3 
           &kCFTypeDictionaryKeyCallBacks, 
           & kCFTypeDictionaryValueCallBacks); 
+1

ठीक है, लेकिन मैंने क्वार्ट्ज का उपयोग करके स्वीकृति उत्तर के खिलाफ इस विधि का परीक्षण किया और स्वीकार्य उत्तर 15 गुना तेज है, विशेष रूप से यदि आपके पास पहले से ही 'UIImage' है, क्योंकि आपको इसे' CFData' में परिवर्तित करना है ताकि आप 'CGImageSourceCreateThumbnailAtIndex' का उपयोग कर सकें। । यह पूरी प्रक्रिया 15 गुना धीमी है। – SpaceDog

3

चालाक त्रुटि के जवाब से ऊपर की स्विफ्ट 2.x संस्करण:

// Define thumbnail size 
    let size = CGSize(width: 100, height: 100) 

    // Define rect for thumbnail 
    let scale = max(size.width/image.size.width, size.height/image.size.height) 
    let width = image.size.width * scale 
    let height = image.size.height * scale 
    let x = (size.width - width)/CGFloat(2) 
    let y = (size.height - height)/CGFloat(2) 
    let thumbnailRect = CGRectMake(x, y, width, height) 

    // Generate thumbnail from image 
    UIGraphicsBeginImageContextWithOptions(size, false, 0) 
    image.drawInRect(thumbnailRect) 
    let thumbnail = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
+1

स्विफ्ट 3 के लिए, चलिए थंबनेल को सीजीआरईटीएक्ट को असाइनमेंट बदलें (एक्स: एक्स, वाई: वाई, चौड़ाई: चौड़ाई, ऊंचाई: ऊंचाई) –

संबंधित मुद्दे