Ich habe bei Google gesucht und bin nur auf Bibliotheken gestoßen, die entweder die Höhe / Breite reduzieren oder das Erscheinungsbild von UIImage über CoreImage bearbeiten. Aber ich habe keine Bibliothek gesehen oder gefunden, in der erklärt wird, wie die Bildgröße reduziert werden kann. Wenn sie hochgeladen wird, ist sie nicht die volle Bildgröße.
Bisher habe ich Folgendes:
if image != nil {
//let data = NSData(data: UIImagePNGRepresentation(image))
let data = UIImagePNGRepresentation(image)
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"image\"; filename=\"randomName\"\r\n")
body.appendString("Content-Type: image/png\r\n\r\n")
body.appendData(data)
body.appendString("\r\n")
}
und es sendet 12 MB Fotos. Wie kann ich das auf 1 MB reduzieren? Vielen Dank!
guard size.width > width else { return self }
damit kleinere Bilder nicht größer werden.Dies ist der Weg, den ich befolgt habe, um die Bildgröße zu ändern.
-(UIImage *)resizeImage:(UIImage *)image { float actualHeight = image.size.height; float actualWidth = image.size.width; float maxHeight = 300.0; float maxWidth = 400.0; float imgRatio = actualWidth/actualHeight; float maxRatio = maxWidth/maxHeight; float compressionQuality = 0.5;//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; } } 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]; }
Mit dieser Methode wurde mein Bild mit 6,5 MB auf 104 KB reduziert.
Swift 4 Code:
func resize(_ image: UIImage) -> UIImage { var actualHeight = Float(image.size.height) var actualWidth = Float(image.size.width) let maxHeight: Float = 300.0 let maxWidth: Float = 400.0 var imgRatio: Float = actualWidth / actualHeight let maxRatio: Float = maxWidth / maxHeight let compressionQuality: Float = 0.5 //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 } } let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(actualWidth), height: CGFloat(actualHeight)) UIGraphicsBeginImageContext(rect.size) image.draw(in: rect) let img = UIGraphicsGetImageFromCurrentImageContext() let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality)) UIGraphicsEndImageContext() return UIImage(data: imageData!) ?? UIImage() }
quelle
Für den Fall, dass jemand mit Swift 3 und 4 die Größe des Bilds auf weniger als 1 MB ändern möchte .
Kopieren Sie einfach diese Erweiterung und fügen Sie sie ein :
extension UIImage { func resized(withPercentage percentage: CGFloat) -> UIImage? { let canvasSize = CGSize(width: size.width * percentage, height: size.height * percentage) UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale) defer { UIGraphicsEndImageContext() } draw(in: CGRect(origin: .zero, size: canvasSize)) return UIGraphicsGetImageFromCurrentImageContext() } func resizedTo1MB() -> UIImage? { guard let imageData = UIImagePNGRepresentation(self) else { return nil } var resizingImage = self var imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB while imageSizeKB > 1000 { // ! Or use 1024 if you need KB but not kB guard let resizedImage = resizingImage.resized(withPercentage: 0.9), let imageData = UIImagePNGRepresentation(resizedImage) else { return nil } resizingImage = resizedImage imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB } return resizingImage } }
Und benutze:
let resizedImage = originalImage.resizedTo1MB()
Bearbeiten: Bitte beachten Sie, dass die Benutzeroberfläche blockiert wird. Wechseln Sie daher zum Hintergrund-Thread, wenn Sie der Meinung sind, dass dies der richtige Weg für Ihren Fall ist.
quelle
while
Schleifen sollteguard
derUIImagePNGRepresentation
AufrufresizedImage
nicht verwendenresizingImage
. Verursacht eine zusätzliche Schleife ...Wie Leo Answer, jedoch nur wenige Änderungen für SWIFT 2.0
extension UIImage { func resizeWithPercentage(percentage: CGFloat) -> UIImage? { let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: size.width * percentage, height: size.height * percentage))) imageView.contentMode = .ScaleAspectFit imageView.image = self UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale) guard let context = UIGraphicsGetCurrentContext() else { return nil } imageView.layer.renderInContext(context) guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil } UIGraphicsEndImageContext() return result } func resizeWithWidth(width: CGFloat) -> UIImage? { let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height))))) imageView.contentMode = .ScaleAspectFit imageView.image = self UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale) guard let context = UIGraphicsGetCurrentContext() else { return nil } imageView.layer.renderInContext(context) guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil } UIGraphicsEndImageContext() return result } }
quelle
Hier ist die Antwort von user4261201, aber in Kürze, die ich derzeit verwende:
func compressImage (_ image: UIImage) -> UIImage { let actualHeight:CGFloat = image.size.height let actualWidth:CGFloat = image.size.width let imgRatio:CGFloat = actualWidth/actualHeight let maxWidth:CGFloat = 1024.0 let resizedHeight:CGFloat = maxWidth/imgRatio let compressionQuality:CGFloat = 0.5 let rect:CGRect = CGRect(x: 0, y: 0, width: maxWidth, height: resizedHeight) UIGraphicsBeginImageContext(rect.size) image.draw(in: rect) let img: UIImage = UIGraphicsGetImageFromCurrentImageContext()! let imageData:Data = UIImageJPEGRepresentation(img, compressionQuality)! UIGraphicsEndImageContext() return UIImage(data: imageData)! }
quelle
Swift4.2
let imagedata = yourImage.jpegData(compressionQuality: 0.1)!
quelle
Wenn Sie ein Bild im
NSData
Format hochladen , verwenden Sie Folgendes :NSData *imageData = UIImageJPEGRepresentation(yourImage, floatValue);
yourImage
ist deinUIImage
.floatvalue
ist der Komprimierungswert (0,0 bis 1,0)Das obige ist, um Bild zu konvertieren
JPEG
.Zur
PNG
Verwendung:UIImagePNGRepresentation
Hinweis: Der obige Code befindet sich in Objective-C. Bitte überprüfen Sie, wie Sie NSData in Swift definieren.
quelle
Mit dieser Option können Sie die gewünschte Größe steuern:
func jpegImage(image: UIImage, maxSize: Int, minSize: Int, times: Int) -> Data? { var maxQuality: CGFloat = 1.0 var minQuality: CGFloat = 0.0 var bestData: Data? for _ in 1...times { let thisQuality = (maxQuality + minQuality) / 2 guard let data = image.jpegData(compressionQuality: thisQuality) else { return nil } let thisSize = data.count if thisSize > maxSize { maxQuality = thisQuality } else { minQuality = thisQuality bestData = data if thisSize > minSize { return bestData } } } return bestData }
Beispiel für einen Methodenaufruf:
jpegImage(image: image, maxSize: 500000, minSize: 400000, times: 10)
Es wird versucht, eine Datei zwischen einer maximalen und einer minimalen Größe von maxSize und minSize abzurufen, aber nur mal versuchen. Wenn es innerhalb dieser Zeit fehlschlägt, wird null zurückgegeben.
quelle
Ich denke, der einfachste Weg, Swift selbst zu komprimieren, um das Bild in komprimierte Daten zu komprimieren, ist der Code in Swift 4.2
let imageData = yourImageTobeCompressed.jpegData(compressionQuality: 0.5)
und Sie können diese imageData senden, um sie auf den Server hochzuladen.
quelle
Ich denke, der Kern der Frage hier ist, wie die Daten eines UIImage vor dem Hochladen auf einen Server zuverlässig auf eine bestimmte Größe verkleinert werden können, anstatt nur das UIImage selbst zu verkleinern.
Die Verwendung
func jpegData(compressionQuality: CGFloat) -> Data?
funktioniert gut, wenn Sie nicht auf eine bestimmte Größe komprimieren müssen. In bestimmten Fällen finde ich es jedoch nützlich, unter einer bestimmten angegebenen Dateigröße komprimieren zu können. In diesem FalljpegData
ist dies unzuverlässig, und das iterative Komprimieren eines Bildes auf diese Weise führt zu einem Plateau der Dateigröße (und kann sehr teuer sein). Stattdessen ziehe ich es vor, die Größe des UIImage selbst wie in Leos Antwort zu reduzieren , dann in jpegData zu konvertieren und iterativ zu überprüfen, ob die reduzierte Größe unter dem von mir gewählten Wert liegt (innerhalb eines von mir festgelegten Bereichs). Ich passe den Multiplikator für den Komprimierungsschritt basierend auf dem Verhältnis der aktuellen Dateigröße zur gewünschten Dateigröße an, um die ersten Iterationen zu beschleunigen, die am teuersten sind (da die Dateigröße zu diesem Zeitpunkt die größte ist).Swift 5
extension UIImage { func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? { let canvas = CGSize(width: size.width * percentage, height: size.height * percentage) let format = imageRendererFormat format.opaque = isOpaque return UIGraphicsImageRenderer(size: canvas, format: format).image { _ in draw(in: CGRect(origin: .zero, size: canvas)) } } func compress(to kb: Int, allowedMargin: CGFloat = 0.2) -> Data { guard kb > 10 else { return Data() } // Prevents user from compressing below a limit (10kb in this case). let bytes = kb * 1024 var compression: CGFloat = 1.0 let step: CGFloat = 0.05 var holderImage = self var complete = false while(!complete) { guard let data = holderImage.jpegData(compressionQuality: 1.0) else { break } let ratio = data.count / bytes if data.count < Int(CGFloat(bytes) * (1 + allowedMargin)) { complete = true return data } else { let multiplier:CGFloat = CGFloat((ratio / 5) + 1) compression -= (step * multiplier) } guard let newImage = holderImage.resized(withPercentage: compression) else { break } holderImage = newImage } return Data() } }
Und Verwendung:
let data = image.compress(to: 1000)
quelle
return data
?compress to 0
Groß- und Kleinschreibung zu verhindern und die Komprimierung auf einen angemessenen Wert zu beschränken (in diesem Beispiel 10 KB).Dies habe ich in Swift 3 getan, um die Größe eines UIImage zu ändern. Es reduziert die Bildgröße auf weniger als 100 KB. Es funktioniert proportional!
extension UIImage { class func scaleImageWithDivisor(img: UIImage, divisor: CGFloat) -> UIImage { let size = CGSize(width: img.size.width/divisor, height: img.size.height/divisor) UIGraphicsBeginImageContext(size) img.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) let scaledImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return scaledImage! } }
Verwendung:
let scaledImage = UIImage.scaleImageWithDivisor(img: capturedImage!, divisor: 3)
quelle
Basierend auf der Antwort von Tung Fam. So ändern Sie die Größe auf eine bestimmte Dateigröße. Wie 0,7 MB können Sie diesen Code verwenden.
extension UIImage { func resize(withPercentage percentage: CGFloat) -> UIImage? { var newRect = CGRect(origin: .zero, size: CGSize(width: size.width*percentage, height: size.height*percentage)) UIGraphicsBeginImageContextWithOptions(newRect.size, true, 1) self.draw(in: newRect) defer {UIGraphicsEndImageContext()} return UIGraphicsGetImageFromCurrentImageContext() } func resizeTo(MB: Double) -> UIImage? { guard let fileSize = self.pngData()?.count else {return nil} let fileSizeInMB = CGFloat(fileSize)/(1024.0*1024.0)//form bytes to MB let percentage = 1/fileSizeInMB return resize(withPercentage: percentage) } }
quelle
Gleiches in Ziel-C:
Schnittstelle:
@interface UIImage (Resize) - (UIImage *)resizedWithPercentage:(CGFloat)percentage; - (UIImage *)resizeTo:(CGFloat)weight isPng:(BOOL)isPng jpegCompressionQuality:(CGFloat)compressionQuality; @end
Implementierung :
#import "UIImage+Resize.h" @implementation UIImage (Resize) - (UIImage *)resizedWithPercentage:(CGFloat)percentage { CGSize canvasSize = CGSizeMake(self.size.width * percentage, self.size.height * percentage); UIGraphicsBeginImageContextWithOptions(canvasSize, false, self.scale); [self drawInRect:CGRectMake(0, 0, canvasSize.width, canvasSize.height)]; UIImage *sizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return sizedImage; } - (UIImage *)resizeTo:(CGFloat)weight isPng:(BOOL)isPng jpegCompressionQuality:(CGFloat)compressionQuality { NSData *imageData = isPng ? UIImagePNGRepresentation(self) : UIImageJPEGRepresentation(self, compressionQuality); if (imageData && [imageData length] > 0) { UIImage *resizingImage = self; double imageSizeKB = [imageData length] / weight; while (imageSizeKB > weight) { UIImage *resizedImage = [resizingImage resizedWithPercentage:0.9]; imageData = isPng ? UIImagePNGRepresentation(resizedImage) : UIImageJPEGRepresentation(resizedImage, compressionQuality); resizingImage = resizedImage; imageSizeKB = (double)(imageData.length / weight); } return resizingImage; } return nil; }
Verwendung :
#import "UIImage+Resize.h" UIImage *resizedImage = [self.picture resizeTo:2048 isPng:NO jpegCompressionQuality:1.0];
quelle
Wenn ich versuche, die akzeptierte Antwort zu verwenden, um die Größe eines Bilds für die Verwendung in meinem Projekt zu ändern, wird es sehr pixelig und verschwommen. Am Ende hatte ich diesen Code, um die Größe von Bildern zu ändern, ohne Pixelung oder Unschärfe hinzuzufügen:
func scale(withPercentage percentage: CGFloat)-> UIImage? { let cgSize = CGSize(width: size.width * percentage, height: size.height * percentage) let hasAlpha = true let scale: CGFloat = 0.0 // Use scale factor of main screen UIGraphicsBeginImageContextWithOptions(cgSize, !hasAlpha, scale) self.draw(in: CGRect(origin: CGPoint.zero, size: cgSize)) let scaledImage = UIGraphicsGetImageFromCurrentImageContext() return scaledImage }
quelle
extension UIImage { func resized(toValue value: CGFloat) -> UIImage { if size.width > size.height { return self.resize(toWidth: value)! } else { return self.resize(toHeight: value)! } }
quelle
Ich war mit den Lösungen hier nicht zufrieden, die ein Bild basierend auf einer bestimmten KB-Größe erzeugen, da die meisten von ihnen verwendet wurden
.jpegData(compressionQuality: x)
. Diese Methode funktioniert nicht mit großen Bildern, da das große Bild auch bei einer auf 0,0 eingestellten Komprimierungsqualität groß bleibt, z. B. 10 MB, die im Hochformat eines neueren iPhone erzeugt werden, immer noch über 1 MB liegen, während die Komprimierungsqualität auf 0,0 eingestellt ist.Deshalb habe ich die Antwort von @Leo Dabus verwendet und sie in eine Hilfsstruktur umgeschrieben, die ein Bild in eine Hintergrundwarteschlange konvertiert:
import UIKit struct ImageResizer { static func resize(image: UIImage, maxByte: Int, completion: @escaping (UIImage?) -> ()) { DispatchQueue.global(qos: .userInitiated).async { guard let currentImageSize = image.jpegData(compressionQuality: 1.0)?.count else { return completion(nil) } var imageSize = currentImageSize var percentage: CGFloat = 1.0 var generatedImage: UIImage? = image let percantageDecrease: CGFloat = imageSize < 10000000 ? 0.1 : 0.3 while imageSize > maxByte && percentage > 0.01 { let canvas = CGSize(width: image.size.width * percentage, height: image.size.height * percentage) let format = image.imageRendererFormat format.opaque = true generatedImage = UIGraphicsImageRenderer(size: canvas, format: format).image { _ in image.draw(in: CGRect(origin: .zero, size: canvas)) } guard let generatedImageSize = generatedImage?.jpegData(compressionQuality: 1.0)?.count else { return completion(nil) } imageSize = generatedImageSize percentage -= percantageDecrease } completion(generatedImage) } } }
Verwendung:
ImageResizer.resize(image: image, maxByte: 800000) { img in guard let resizedImage = img else { return } // Use resizedImage } }
quelle
Ändern Sie die Größe des UIImage mit .resizeToMaximumBytes
quelle