2013-09-08 3 views
9

Ich erstelle eine App, mit der der Benutzer ein Foto aufnehmen oder aus der Bibliothek auf dem iPhone auswählen und in das Parse-Backend hochladen kann.Bilder komprimieren, um die Dateigröße zu reduzieren

Das Problem, mit dem ich konfrontiert bin, betrifft die Größe der Datei.

Ich habe gelesen, was große Spieler wie Facebook, Twitter, Instagram und Google in Bezug auf Auflösung und Dateigröße machen, aber ich kann nicht näher kommen.

Ich bin sicher, dass sie den besten Code und die besten Tools haben, um das zu tun, aber ich werde mich freuen, sie so gut wie möglich mit den regulären iOS-Prozessen zu implementieren.

Das ist, was ich jetzt tun:

- (UIImage *)normalResImageForAsset:(ALAsset*)asset 
{ 
    // Convert ALAsset to UIImage 
    UIImage *image = [self highResImageForAsset:asset]; 

    // Determine output size 
    CGFloat maxSize = 1024.0f; 
    CGFloat width = image.size.width; 
    CGFloat height = image.size.height; 
    CGFloat newWidth = width; 
    CGFloat newHeight = height; 

    // If any side exceeds the maximun size, reduce the greater side to 1200px and proportionately the other one 
    if (width > maxSize || height > maxSize) { 
     if (width > height) { 
      newWidth = maxSize; 
      newHeight = (height*maxSize)/width; 
     } else { 
      newHeight = maxSize; 
      newWidth = (width*maxSize)/height; 
     } 
    } 

    // Resize the image 
    CGSize newSize = CGSizeMake(newWidth, newHeight); 
    UIGraphicsBeginImageContext(newSize); 
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    // Set maximun compression in order to decrease file size and enable faster uploads & downloads 
    NSData *imageData = UIImageJPEGRepresentation(newImage, 0.0f); 
    UIImage *processedImage = [UIImage imageWithData:imageData]; 

    return processedImage; 
} 

Ich versuche 1024px die maximun zulässige Größe (beide mit ot Höhe), um einige Einschränkungen dort zu beginnen und ich bin Anwendung maximun dann Komprimierung, um die Größe zu reduzieren.

Das funktioniert und schneidet ungefähr 50% der Bildgröße, ohne JPEGs wirklich zu beschädigen, aber es ist immer noch sehr viel. Besonders, wenn Fotos mit der Kamera des Telefons aufgenommen und hochgeladen werden. Das verarbeitete Bild kann immer noch 1MB groß sein, was viel zu viel ist.

Ich vermute, dass ich einige nützliche Schritte vermissen oder die falsche Technik verwenden könnte.

Jede Rückmeldung würde sehr geschätzt werden.

+0

ich über die Rundreise von UIImage zu NSData frage mich, und zu UIImage zurück. Haben Sie [imageData length] vor der Initialisierung eines neuen UIImage überprüft? Vielleicht möchten Sie das codierte NSData-Objekt von dieser Funktion zurückgeben, damit Sie das Byte-Array auf den Server hochladen können. – umlum

+0

Erlaubt dem Benutzer, die Bildgröße zu wählen und sie bei Bedarf über die zu hochzuladende Datengröße zu warnen. – Wain

+0

@Wain Aber das OP ist richtig, dass bei 1024x768px ein vollständig komprimiertes JPEG-Bild nicht 1MB aufnehmen sollte. – umlum

Antwort

9

Ich hatte ein ähnliches Problem und ich dachte auch, dass die Komprimierung nicht funktionierte. Es stellte sich anderswo in meinem Code heraus, dass ich die Datei mit unterschiedlicher Komprimierung auf die Festplatte geschrieben habe. Sie können das gleiche mit den Daten tun, die diese Funktion zurückgibt. Ein guter Weg, um sicherzustellen, dass in der Tat die Kompression wirksam ist, ist so etwas wie dies zu tun:

NSData *imgData1 = UIImageJPEGRepresentation(newImage, 1.0f); 
NSLog(@"1.0 size: %d", imgData1.length); 

NSData *imgData2 = UIImageJPEGRepresentation(newImage, 0.7f); 
NSLog(@"0.7 size: %d", imgData2.length); 

NSData *imgData3 = UIImageJPEGRepresentation(newImage, 0.4f); 
NSLog(@"0.4 size: %d", imgData3.length); 

NSData *imgData4 = UIImageJPEGRepresentation(newImage, 0.0f); 
NSLog(@"0.0 size: %d", imgData4.length); 

// Don't convert NSData back to UIImage before writing to disk 
[imgData4 writeToFile:imagePath atomically:YES]; 

ich ein Bild bin mit, dass 640x480 ist und ich im Bereich Dateigrößen von 325 kB (1,0) bis zu 18 kB (für 0,0)

+0

es funktioniert nicht für mich ... – RaviJSS

+0

Sobald es auf den Server hochgeladen und es möglicherweise nicht in der Lage, das tatsächliche Bild zu rekonstruieren. Kann nicht in allen Szenarien nützlich sein. – Satyam

0

Swift-3 Version von @codeMonkey: -

Es perfekte in Kompression von Bild arbeiten.

func compressImage() -> UIImage { 

     let oldImage = UIImage(named: "background.jpg") 
     var imageData = Data(UIImagePNGRepresentation(oldImage!)!) 
     print("***** Uncompressed Size \(imageData.description) **** ") 

     imageData = UIImageJPEGRepresentation(oldImage!, 0.025)! 
     print("***** Compressed Size \(imageData.description) **** ") 

     let image = UIImage(data: imageData) 
     return image! 

    } 

enter image description here

+0

Was ist mit der Qualität des Bildes? – Satyam

+0

Durch Kompression wird sich die Qualität ändern. – Shrawan

+0

Es reduziert die Qualität des Bildes. Also, es könnte nicht die richtige Lösung sein. – Satyam

0
Please Try below answer. 

+(UIImage *)compressImage:(UIImage *)image{ 
float actualHeight = image.size.height; 
float actualWidth = image.size.width; 
float maxHeight = 1136.0f; 
float maxWidth = 640.0f; 
float imgRatio = actualWidth/actualHeight; 
float maxRatio = maxWidth/maxHeight; 
float compressionQuality = 1;//50 percent compression 

if (actualHeight > maxHeight || actualWidth > maxWidth){ 
    if(imgRatio < maxRatio){ 
     //adjust width according to maxHeight 
     imgRatio = maxHeight/actualHeight; 
     actualWidth = imgRatio * actualWidth; 
     actualHeight = maxHeight; 
    } 
    else if(imgRatio > maxRatio){ 
     //adjust height according to maxWidth 
     imgRatio = maxWidth/actualWidth; 
     actualHeight = imgRatio * actualHeight; 
     actualWidth = maxWidth; 
    } 
    else{ 
     actualHeight = maxHeight; 
     actualWidth = maxWidth; 
    } 
}else{ 
    actualHeight = maxHeight; 
    actualWidth = maxWidth; 
    compressionQuality = 1; 
} 

CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight); 
UIGraphicsBeginImageContext(rect.size); 
[image drawInRect:rect]; 
UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 
NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality); 
UIGraphicsEndImageContext(); 

return [UIImage imageWithData:imageData]; 
}