Wie kann ich Bilder unter iOS komprimieren / in der Größe ändern, bevor ich sie auf einen Server hochlade?

75

Ich lade gerade ein Bild mit Imgur unter iOS mit dem folgenden Code auf einen Server hoch:

NSData* imageData = UIImagePNGRepresentation(image);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* fullPathToFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"SBTempImage.png"];
[imageData writeToFile:fullPathToFile atomically:NO];

[uploadRequest setFile:fullPathToFile forKey:@"image"];

Der Code funktioniert einwandfrei, wenn er im Simulator ausgeführt und eine Datei aus der Fotobibliothek des Simulators hochgeladen wird, da ich eine schnelle Ethernet-Verbindung habe. Der gleiche Code läuft jedoch auf dem iPhone ab, wenn Sie ein mit dem iPhone aufgenommenes Bild auswählen. Also habe ich es versucht, indem ich ein kleines Bild aus dem Web gespeichert und versucht habe, das hochzuladen, was funktioniert hat.

Dies lässt mich glauben, dass die großen Bilder, die vom iPhone aufgenommen wurden, über das etwas langsame 3G-Netzwerk ablaufen. Gibt es eine Möglichkeit, das Bild vom iPhone vor dem Senden zu komprimieren / in der Größe zu ändern?

Joshholat
quelle

Antworten:

-36

Sie sollten in der Lage sein, ein kleineres Bild zu erstellen, indem Sie so etwas tun

UIImage *small = [UIImage imageWithCGImage:original.CGImage scale:0.25 orientation:original.imageOrientation];

(für ein Bild in Viertelgröße) Konvertieren Sie dann das kleinere Bild in ein PNG oder ein beliebiges Format.

TerryH
quelle
52
Dies ändert die gemeldete Größe des skalierten Bildes, ändert jedoch nicht die Bilddaten. Die Datenlänge der auf dem Original und dem skalierten Bild generierten NSData ist praktisch identisch.
Joshua Sullivan
13
Das funktioniert nicht! Dies sollte nicht die akzeptierte Antwort sein! Ich habe es gerade in meine App implementiert, nur um herauszufinden, dass das auf 25% der ursprünglichen Bildgröße komprimierte Bild immer noch dieselbe Größe in Bytes wie das Original hat. Ich habe keine Ahnung, warum es so viele positive Stimmen oder diese nicht funktionierende Antwort gibt!
Michael
funktioniert nicht skaliert das Bild, lässt aber die Daten in voller Größe.
Nicht
Auch hier funktioniert nicht. Bitte entfernen / aktualisieren Sie diese Antwort, um keine Zeit mehr zu verschwenden.
Zorayr
Die Dateigröße wird nicht geändert, da die Deep-Kopie eines UIImage ein CGImage ist und die Größenänderung das Bild nicht ändert. Informationen zum Ändern der Dateigröße finden Sie in den Apple-Dokumenten. Sie erstellen ein neues Bild mit der skalierten Version. Erfahren Sie, was ein Zeiger ist. Lassen Sie es auch wissen, dass das Verkleinern und Verkleinern zu einem Bildverlust führt. Wenn Sie es für wichtige Zwecke verwenden, sieht es später unscharf aus. Komprimieren Sie es und verwenden Sie JPegCompress oder wie auch immer die Funktion heißt, und senden Sie es.
Nick Turner
202

Dieses Snippet ändert die Bildgröße:

UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Die Variable newSizeist a CGSizeund kann wie folgt definiert werden:

CGSize newSize = CGSizeMake(100.0f, 100.0f);
Tuan Nguyen
quelle
1
Dies ist die Lösung, die tatsächlich zu funktionieren scheint (die Größe der Bilddaten stieg von 145.000 auf 30.000).
Joshua Sullivan
9
"newSize" ist CGSize, z. CGSize newSize = CGSizeMake (100.0f, 100.0f);
Dexter
Großartig! Beeilen Sie sich nicht für Komprimierungstechniken, einfachste und gute Lösung :)
DivineDesert
Dies ändert jedoch die Größe des Bildes. Wenn ich ein Bild mit der ursprünglichen Spezifikation auf den Server hochladen muss, funktioniert dies nicht, oder?
Nuzhat Zari
Ist dies die Größe "newSize" der ImageSize in Pixel?
Stephan Boner
38

Eine in sich geschlossene Lösung:

- (UIImage *)compressForUpload:(UIImage *)original scale:(CGFloat)scale
{
    // Calculate new size given scale factor.
    CGSize originalSize = original.size;
    CGSize newSize = CGSizeMake(originalSize.width * scale, originalSize.height * scale);

    // Scale the original image to match the new size.
    UIGraphicsBeginImageContext(newSize);
    [original drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *compressedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return compressedImage;
}

Vielen Dank an @Tuan Nguyen.

Zorayr
quelle
16

Als Ergänzung zu @Tuan Nguyen ist dies möglicherweise der schnellste und eleganteste Weg, dies zu tun.

Um auf John Muchows Beitrag auf iphonedevelopertips.com zu verlinken , ist das Hinzufügen einer Kategorie zu einem UIImage eine sehr sehr praktische Möglichkeit, sehr schnell zu skalieren. Ich rufe einfach an

    UIImage *_image = [[[UIImage alloc] initWithData:SOME_NSDATA] scaleToSize:CGSizeMake(640.0,480.0)];

gibt Ihnen ein 640x480-Repräsentationsbild Ihrer NSDATA (das ein Online-Bild sein kann) ohne weitere Codezeile zurück.

Nembleton
quelle
1
Es verkleinert tatsächlich die Pixel. Dadurch wird auch die Größe des Bilds verringert. Aber es macht per se keine "Rekompression". Wenn Sie das hier erwähnen.
Nembleton
6

In diesem Code bedeutet 0,5 50% ...

UIImage *original = image;
UIImage *compressedImage = UIImageJPEGRepresentation(original, 0.5f);
Jagandeep Singh
quelle
Das war genau das, was ich brauchte.
Scott
4

Verwenden Sie diese einfache Methode NSData *data = UIImageJPEGRepresentation(chosenImage, 0.2f);


quelle
3

Schnelle Implementierung der Zorayr-Funktion (mit einer kleinen Änderung, um Höhen- oder Breitenbeschränkungen durch tatsächliche Einheiten ohne Skalierung einzuschließen):

class func compressForUpload(original:UIImage, withHeightLimit heightLimit:CGFloat, andWidthLimit widthLimit:CGFloat)->UIImage{

    let originalSize = original.size
    var newSize = originalSize

    if originalSize.width > widthLimit && originalSize.width > originalSize.height {

        newSize.width = widthLimit
        newSize.height = originalSize.height*(widthLimit/originalSize.width)
    }else if originalSize.height > heightLimit && originalSize.height > originalSize.width {

        newSize.height = heightLimit
        newSize.width = originalSize.width*(heightLimit/originalSize.height)
    }

    // Scale the original image to match the new size.
    UIGraphicsBeginImageContext(newSize)
    original.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let compressedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return compressedImage
}
PJeremyMalouf
quelle
2
Diese Lösung ist nett, funktioniert aber nicht für quadratische Bilder. wegen originalSize.width> originalSize.height und originalSize.height> originalSize.width ändern Sie also besser eins zu> = :-)
rcpfuchs
0
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution {
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                                                       (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                                                       (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                                                       (id) kCGImageSourceThumbnailMaxPixelSize : @(resolution)
                                                       };
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail];
return img;
}
Vineet Ravi
quelle
0

Swift 2.0-Version der Jagandeep Singh-Methode, müssen aber Daten in Bilder konvertieren, weil NSData? wird UIImage nicht automatisch konvertiert.

let orginalImage:UIImage = image

let compressedData = UIImageJPEGRepresentation(orginalImage, 0.5)
let compressedImage = UIImage(data: compressedData!)
CodeOverRide
quelle
0
NsData *data=UiImageJPEGRepresentation(Img.image,0.2f);
iOS Lifee
quelle
1
Es ist normalerweise hilfreich, solche Antworten auszuarbeiten. Bereitstellung von Links zur Dokumentation, Zitaten aus dieser Dokumentation sowie einer Erklärung, warum Ihr Code die Frage beantwortet.
Tschad
0
UIImage *image = [UIImage imageNamed:@"image.png"];
NSData *imgData1 = UIImageJPEGRepresentation(image, 1);
NSLog(@"Original --- Size of Image(bytes):%d",[imgData1 length]);

NSData *imgData2 = UIImageJPEGRepresentation(image, 0.5);
NSLog(@"After --- Size of Image(bytes):%d",[imgData2 length]);
image = [UIImage imageWithData:imgData2];
imgTest.image = image;

Versuchen Sie, JPG durch Skalierungsfaktor zu konvertieren. Hier verwende ich 0,5 In meinem Fall: Original --- Bildgröße (Bytes): 85 KB & danach --- Bildgröße (Bytes): 23 KB

Swatee Salunkhe
quelle
-1
-(UIImage *) resizeImage:(UIImage *)orginalImage resizeSize:(CGSize)size
{
CGFloat actualHeight = orginalImage.size.height;
CGFloat actualWidth = orginalImage.size.width;
//  if(actualWidth <= size.width && actualHeight<=size.height)
//  {
//      return orginalImage;
//  }
float oldRatio = actualWidth/actualHeight;
float newRatio = size.width/size.height;
if(oldRatio < newRatio)
{
    oldRatio = size.height/actualHeight;
    actualWidth = oldRatio * actualWidth;
    actualHeight = size.height;
}
else
{
    oldRatio = size.width/actualWidth;
    actualHeight = oldRatio * actualHeight;
    actualWidth = size.width;
}

CGRect rect = CGRectMake(0.0,0.0,actualWidth,actualHeight);
UIGraphicsBeginImageContext(rect.size);
[orginalImage drawInRect:rect];
orginalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return orginalImage;
 }

Dies ist der Methodenaufruf

 UIImage *compimage=[appdel resizeImage:imagemain resizeSize:CGSizeMake(40,40)];      

Es gibt ein Bild zurück. Dieses Bild kann überall angezeigt werden.

Mahesh Chowdary
quelle