2011-01-17 14 views
36

Größe ändern Ich habe eine Anwendung, wo ich große Bilder auf kleinem Raum anzeigen. Die Bilder sind ziemlich groß, aber ich zeige sie nur in 100x100 Pixel Rahmen. Meine App reagiert langsam aufgrund der Größe der Bilder, die ich verwende.Wie das Bild programmgesteuert in Objektiv-c in iPhone

Um die Leistung zu verbessern, wie kann ich die Bilder mithilfe von Objective-C programmgesteuert ändern?

+1

Siehe http://stackoverflow.com/questions/2658738/the-simplest-way-to- resize-an-uiimage – Costique

+0

Ich habe Code geschrieben, um ein Bild um den Faktor zwei zu verkleinern, indem ich durch die Pixel gehe und 4 Pixel zu einem summiere. Es funktionierte ziemlich gut (bessere Bildqualität als mit der Systemskalierung), aber war vielleicht 50 Zeilen Code und nicht wirklich hübsch. (Dann entdeckte ich, dass ich das Bild sowieso nicht skalieren musste.) –

+0

Hier ist der Thread, wo mein Algorithmus gefunden werden kann: http: // stackoverflow.com/questions/6052188/high-quality-scaling-of-uiimage –

Antwort

87

Hier finden Sie den folgenden Code.

- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size { 
    UIGraphicsBeginImageContext(size); 
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
    UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 
    return destImage; 
} 
+2

Dies hat in der Vergangenheit funktioniert, aber in iOS5. 0.1 Dies führt zu einem Speicherleck. Irgendeine andere Möglichkeit, dies zu erreichen? http://stackoverflow.com/questions/8236837/memory-leak-drainrect-on-ios5-0-1 – David

+0

Ist das immer noch ein Problem mit iOS 6.x? – Paaske

+0

Ja, es führt immer noch zu Speicherverlust ... –

0

Da der Code in iOS 4 perfekt lief, habe ich aus Gründen der Abwärtskompatibilität eine Überprüfung für die OS-Version vorgenommen und für alles unter 5.0 würde der alte Code funktionieren.

- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { 
    BOOL drawTransposed; 
    CGAffineTransform transform = CGAffineTransformIdentity; 

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) { 
     // Apprently in iOS 5 the image is already correctly rotated, so we don't need to rotate it manually 
     drawTransposed = NO; 
    } else {  
     switch (self.imageOrientation) { 
      case UIImageOrientationLeft: 
      case UIImageOrientationLeftMirrored: 
      case UIImageOrientationRight: 
      case UIImageOrientationRightMirrored: 
       drawTransposed = YES; 
       break; 

      default: 
       drawTransposed = NO; 
     } 

     transform = [self transformForOrientation:newSize]; 
    } 

    return [self resizedImage:newSize 
        transform:transform 
       drawTransposed:drawTransposed 
     interpolationQuality:quality]; 
} 
+2

Es sieht so aus, als würde sich der Code selbst aufrufen, ohne anzuhalten. – Binarian

4

Mein Liebling Weg, dies zu tun, ist mit CGImageSourceCreateThumbnailAtIndex (im Rahmen ImageIO). Der Name ist ein bisschen irreführend.

Hier ist ein Auszug von Code aus einer aktuellen App von mir.

CGFloat maxw = // whatever; 
CGFloat maxh = // whatever; 

CGImageSourceRef src = NULL; 
if ([imageSource isKindOfClass:[NSURL class]]) 
    src = CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil); 
else if ([imageSource isKindOfClass:[NSData class]]) 
    src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil); 

// if at double resolution, double the thumbnail size and use double-resolution image 
CGFloat scale = 1; 
if ([[UIScreen mainScreen] scale] > 1.0) { 
    scale = 2; 
    maxw *= 2; 
    maxh *= 2; 
} 

// load the image at the desired size 
NSDictionary* d = @{ 
        (id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue, 
        (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue, 
        (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue, 
        (id)kCGImageSourceThumbnailMaxPixelSize: @((int)(maxw > maxh ? maxw : maxh)) 
        }; 
CGImageRef imref = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d); 
if (NULL != src) 
    CFRelease(src); 
UIImage* im = [UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp]; 
if (NULL != imref) 
    CFRelease(imref); 
0

Sie können dies verwenden.

[m_Image.layer setMinificationFilter:kCAFilterTrilinear];

+0

Dies ist für UIImageView und nicht für UIImage – vinceville

2

Wenn Sie ein Bild auf verschiedenen Größen verwenden und jedes Mal, Ändern der Größe Ihrer Anwendung die Leistung beeinträchtigen wird. Die Lösung besteht darin, die Größe nicht zu ändern. Verwenden Sie einfach den Button anstelle von imageview. und stellen Sie einfach das Bild auf die Schaltfläche, es wird automatisch die Größe ändern und Sie werden eine großartige Leistung erhalten.

Ich habe auch die Größe der Bilder geändert, während ich sie auf Zelle setzte, aber meine App wurde langsam. Also habe ich Button anstelle von Bildansicht verwendet (nicht die Größe der Bilder programmatisch ändern tut diese Aufgabe) und es funktioniert einwandfrei.

5

Dieser Code ist nur für die Änderung Bildskala nicht für die Größenänderung Sie müssen CGSize als Bildbreite und -höhe einstellen, damit sich das Bild nicht dehnt und in der Mitte anordnet.

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

Dies funktioniert perfekt für mich, vielen Dank. –

+0

Viel Spaß beim Codieren @NishadArora :) –

1
-(UIImage *)scaleImage:(UIImage *)image toSize:.  (CGSize)targetSize 
    { 
//If scaleFactor is not touched, no scaling will occur 
    CGFloat scaleFactor = 1.0; 

//Deciding which factor to use to scale the image (factor = targetSize/imageSize) 
if (image.size.width > targetSize.width || 
    image.size.height > targetSize.height || image.size.width == image.size.height) 
    if (!((scaleFactor = (targetSize.width/
    image.size.width)) > (targetSize.height/
     image.size.height))) //scale to fit width, or 
     scaleFactor = targetSize.height/image.size.height; // scale to fit heigth. 
0

Dieser Thread ist alt, aber es ist das, was ich hochgezogen, wenn dieses Problem zu lösen versuchen. Sobald das Bild skaliert wurde, wurde es in meinem Container nicht gut angezeigt, obwohl ich das automatische Layout deaktiviert habe. Der einfachste Weg für mich, dies für die Anzeige in einer Tabellenzeile zu lösen, bestand darin, das Bild auf einen weißen Hintergrund zu malen, der eine feste Größe hatte.

Helper Funktion

+(UIImage*)scaleMaintainAspectRatio:(UIImage*)sourceImage :(float)i_width :(float)i_height 
{ 
float newHeight = 0.0; 
float newWidth = 0.0; 

float oldWidth = sourceImage.size.width; 
float widthScaleFactor = i_width/oldWidth; 

float oldHeight = sourceImage.size.height; 
float heightScaleFactor = i_height/oldHeight; 
if (heightScaleFactor > widthScaleFactor) { 
    newHeight = oldHeight * widthScaleFactor; 
    newWidth = sourceImage.size.width * widthScaleFactor; 
} else { 
    newHeight = sourceImage.size.height * heightScaleFactor; 
    newWidth = oldWidth * heightScaleFactor; 
} 

// return image in white rect 
float cxPad = i_width - newWidth; 
float cyPad = i_height - newHeight; 
if (cyPad > 0) { 
    cyPad = cyPad/2.0; 
} 
if (cxPad > 0) { 
    cxPad = cxPad/2.0; 
} 

CGSize size = CGSizeMake(i_width, i_height); 
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0); 
[[UIColor whiteColor] setFill]; 
UIRectFill(CGRectMake(0, 0, size.width, size.height)); 
[sourceImage drawInRect:CGRectMake((int)cxPad, (int)cyPad, newWidth, newHeight)]; 
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
return newImage; 

// will return scaled image at actual size, not in white rect 
// UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)); 
// [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)]; 
// UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
// UIGraphicsEndImageContext(); 
// return newImage; 
} 

Ich nannte dies wie folgt aus meiner Tabellenansicht cellForRowAtIndexPath

PFFile *childsPicture = [object objectForKey:@"picture"]; 
[childsPicture getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) { 
    if (!error) { 
     UIImage *largePicture = [UIImage imageWithData:imageData]; 
     UIImage *scaledPicture = [Utility scaleMaintainAspectRatio:largePicture :70.0 :70.0 ]; 
     PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100]; 
     thumbnailImageView.image = scaledPicture; 
     [self.tableView reloadData]; 
    } 
}]; 
Verwandte Themen