2016-08-12 6 views
1

Ich habe jeden Stack-Überlaufposten und Video online durchgesehen und finde keine Lösung, die richtig funktioniert. Im Moment wählt der Benutzer ein Foto aus, das komprimiert werden soll, bevor es in einen AWS S3-Bucket hochgeladen wird. Der Upload funktioniert einwandfrei, aber aus irgendeinem Grund ist das komprimierte Bild größer als das Originalbild! Zum Beispiel, wenn der Benutzer ein 9KB Foto auswählt, wenn ich zu S3 hochlade, ist das Foto 28.5KB. Ich habe versucht ein anderes Foto und es ist 48KB und nach "Kompression" auf S3 seine 378.9KB! (Ich benutze die neueste Softwareversion von allem und kompiliere mit dem Simulator)Wie komprimiere ich Bilder in iOS?

Ich möchte das Originalbild so viel wie ich vor dem Hochladen komprimieren.

Das ist, was ich bisher habe:

Wie ich "komprimieren", um das Bild:

UIImage *compressedProductImage; 
NSData *NSproductImage; 
NSUInteger productImageSize; 

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ 
    self.productImage = info[UIImagePickerControllerOriginalImage]; 
    [self.productImageImageView setImage:self.productImage]; 
    [self dismissViewControllerAnimated:YES completion:nil]; 

    NSproductImage = UIImageJPEGRepresentation(self.productImage, 0.5f); 
    productImageSize = [NSproductImage length]; 

    compressedProductImage = [UIImage imageWithData: NSproductImage]; 

Wie ich das Foto hochladen:

//Convert product UIImage 
NSArray *productImagePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *productImageFilePath = [[productImagePaths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@".png"]]; 
[UIImagePNGRepresentation(compressedProductImage) writeToFile:productImageFilePath atomically:YES]; 
NSURL *productImageFileUrl = [NSURL fileURLWithPath:productImageFilePath]; 

uploadRequest.body = productImageFileUrl;//Needs to be a NSURL 
uploadRequest.bucket = AWS_BUCKET_NAME; 
uploadRequest.key = productImageKey; 
uploadRequest.contentType = @"image/png"; 
uploadRequest.ACL = AWSS3BucketCannedACLPublicRead; 

[[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task) { 
    if (task.error != nil) { 
     NSLog(@"%s %@","Error uploading (product image):", uploadRequest.key); 
    }else{ 
     NSLog(@"Product image upload completed"); 
    } 
    return nil; 
}]; 

Antwort

3

Sie don Komprimiere eigentlich nichts. Sie beginnen mit einem UIImage. Dies ist eine vollständige Pixel-für-Pixel-Darstellung, die (typischerweise) Breite x Höhe x 4 Byte benötigt.

Sie konvertieren das dann zu einem JPG mit etwas Kompression. So ist NSproductImage eine viel kleinere Darstellung der JPG-Version des Bildes im Speicher. Dies ist die angenommene kleinere Größe, die Sie sehen, wo Sie denken, dass sie jetzt komprimiert ist.

Aber dann konvertieren Sie diese JPG-Daten zurück in UIImage als compressedProductImage. Diese neue UIImage hat immer noch die gleiche Breite und Höhe der ursprünglichen UIImage. Als Ergebnis nimmt es immer noch die gleiche Breite x Höhe x 4 Bytes wie das Original. Aufgrund der JPG-Komprimierung ist es nur von geringerer Qualität als das Original.

Jetzt konvertieren Sie die aktualisierte UIImage in ein PNG. Da PNG verlustfrei ist, komprimiert es nicht annähernd so viel wie der JPG-Versuch. Sie senden dann diese größere PNG-Version des Bildes an Amazon.

Sie sollten zuerst den sinnlosen Code entfernen, der zuerst in JPG und dann zurück in UIImage konvertiert wird.

An dieser Stelle sollten Sie entweder mit der Größe des PNG leben oder stattdessen JPG verwenden und das kleinere JPG an Amazon senden.

Eine andere Möglichkeit wäre, das Bild zu skalieren, bevor es an Amazon gesendet wird.

+0

So sieht es aus wie es entweder zu kompliziert oder nicht lohnt es überhaupt das Bild vor dem Hochladen zu komprimieren. Ich denke, ich werde mich mit den größeren Bildern beschäftigen und dann an einem besseren Caching-System arbeiten, danke für die aufschlussreiche Antwort! –

3

Wie rmaddy darauf hinweist, nehmen Sie das ausgewählte Bild, konvertieren es in JPEG, konvertieren zurück in eine UIImage (verlieren alle Vorteile der JPEG-Komprimierung) und konvertieren es dann in ein PNG, das eine moderate Komprimierung anbietet. Im Allgemeinen weit weniger Komprimierung als das Original-JPEG aus der Benutzer-Foto-Bibliothek.

Sie haben ein paar Optionen.

  1. Sie können das Original imageData aus dem Vermögenswert in Ihren Fotos Bibliothek abrufen wie in https://stackoverflow.com/a/32845656/1271826 gezeigt, wodurch die Vermeidung es durch ein UIImage überhaupt Round-Tripping. Auf diese Weise erhalten Sie die Qualität des ursprünglichen Bilds, bewahren die mit diesem Bild verknüpften Metadaten und genießen die anständige Komprimierung des ursprünglichen Inhalts.

  2. Sie können das aufgenommene Bild als UIImage nehmen und eine Kombination aus tun:

    • reduzieren die Abmessungen des Bildes, bevor Sie UIImageJPEGRepresentation aufrufen (https://stackoverflow.com/a/10491692/1271826 für Probe-Algorithmus sehen); und/oder

    • Verwenden Sie UIImageJPEGRepresentation mit einer Qualität von weniger als 1,0, je kleiner die Zahl, desto mehr Kompression, aber desto mehr Bildqualität Verlust.

+0

So sieht es entweder zu kompliziert aus oder es lohnt sich überhaupt nicht das Bild vor dem Upload zu komprimieren. Ich denke, ich werde mich mit den größeren Bildern beschäftigen und dann an einem besseren Caching-System arbeiten, danke für die aufschlussreiche Antwort! –

+0

Ich bin nicht sicher, was Sie mit zu kompliziert meinen. Wenn 'didFinishPickingMediaWithInfo' aufgerufen wird, greifen Sie einfach auf' UIImagePickerControllerReferenceURL', holen Sie das Original-Asset aus dem 'PHImageManager' und senden Sie es dann. Es ist super einfach. Sie erhalten Original-Inhalte, es ist schön und klein, keine Bildqualität oder Metadatenverlust, und Sie vermeiden all diese komplizierte Konvertierung in JPEG und eine andere Konvertierung in PNG. Aber jedem sein eigenes. – Rob

Verwandte Themen