How to convert image into binary format in iOS?
You can use the CoreGraphics
' method UIImagePNGRepresentation(UIImage *image)
, which returns NSData
and save it.
and if you want to convert it into again UIImage
create it using [UIimage imageWithData:(NSData *data)]
method.
Demo to send your UIImage to Server
- (void)sendImageToServer {
UIImage *yourImage= [UIImage imageNamed:@"image.png"];
NSData *imageData = UIImagePNGRepresentation(yourImage);
NSString *postLength = [NSString stringWithFormat:@"%d", [imageData length]];
// Init the URLRequest
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"POST"];
[request setURL:[NSURL URLWithString:[NSString stringWithString:@"http://yoururl.domain"]]];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:imageData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
}
[request release];
}
How to convert image to binary in Swift
The ImageDisplay.image
is already a UIImage
. So you needn't to convert it to UIImage
again. Just do that:
let imageData = UIImagePNGRepresentation(ImageDisplay.image)
print(imageData)
converting image to binary in swift
A couple of observations:
Make sure you're doing a test on a device with a release build (or optimizations turned off). That alone makes it much faster. On iPhone 7+ it reduced the conversion of 1920 x 1080 pixel color image to grayscale from 1.7 seconds to less than 0.1 seconds.
You might want to use
DispatchQueue.concurrentPerform
to process pixels concurrently. On my iPhone 7+, that made it about twice as fast.
In my experience Core Image filters weren't much faster, but you can contemplate vImage or Metal if you need it much faster. But unless you're dealing with extraordinarily large images, the response time with optimized (and possibly concurrent) simple Swift code might be sufficient.
An unrelated observation:
- Also, I'm not sure how your conversion to black and white works, but often you'd want to calculate the relative luminance of the color pixel (e.g. 0.2126 * red + 0.7152 * green + 0.0722 * blue). Certainly when converting color image to grayscale you'd do something like that to get an image that more closely represents what the human eye can see, and I'd personally do something like that if converting to black and white, too.
FYI, my Swift 3/4 color-to-grayscale routine looks like:
func blackAndWhite(image: UIImage, completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
// get information about image
let imageref = image.cgImage!
let width = imageref.width
let height = imageref.height
// create new bitmap context
let bitsPerComponent = 8
let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = Pixel.bitmapInfo
let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)!
// draw image to context
let rect = CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))
context.draw(imageref, in: rect)
// manipulate binary data
guard let buffer = context.data else {
print("unable to get context data")
completion(nil)
return
}
let pixels = buffer.bindMemory(to: Pixel.self, capacity: width * height)
DispatchQueue.concurrentPerform(iterations: height) { row in
for col in 0 ..< width {
let offset = Int(row * width + col)
let red = Float(pixels[offset].red)
let green = Float(pixels[offset].green)
let blue = Float(pixels[offset].blue)
let alpha = pixels[offset].alpha
let luminance = UInt8(0.2126 * red + 0.7152 * green + 0.0722 * blue)
pixels[offset] = Pixel(red: luminance, green: luminance, blue: luminance, alpha: alpha)
}
}
// return the image
let outputImage = context.makeImage()!
completion(UIImage(cgImage: outputImage, scale: image.scale, orientation: image.imageOrientation))
}
}
struct Pixel: Equatable {
private var rgba: UInt32
var red: UInt8 {
return UInt8((rgba >> 24) & 255)
}
var green: UInt8 {
return UInt8((rgba >> 16) & 255)
}
var blue: UInt8 {
return UInt8((rgba >> 8) & 255)
}
var alpha: UInt8 {
return UInt8((rgba >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
rgba = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
}
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: Pixel, rhs: Pixel) -> Bool {
return lhs.rgba == rhs.rgba
}
}
Clearly, if you want to convert it to absolute black and white, then adjust the algorithm accordingly, but this illustrates a concurrent image buffer manipulation routine.
While the above is reasonably fast (again, in optimized release builds), using vImage is even faster. The following is adapted from Converting Color Images to Grayscale:
func grayscale(of image: UIImage) -> UIImage? {
guard var source = sourceBuffer(for: image) else { return nil }
defer { free(source.data) }
var destination = destinationBuffer(for: source)
// Declare the three coefficients that model the eye's sensitivity
// to color.
let redCoefficient: Float = 0.2126
let greenCoefficient: Float = 0.7152
let blueCoefficient: Float = 0.0722
// Create a 1D matrix containing the three luma coefficients that
// specify the color-to-grayscale conversion.
let divisor: Int32 = 0x1000
let fDivisor = Float(divisor)
var coefficients = [
Int16(redCoefficient * fDivisor),
Int16(greenCoefficient * fDivisor),
Int16(blueCoefficient * fDivisor)
]
// Use the matrix of coefficients to compute the scalar luminance by
// returning the dot product of each RGB pixel and the coefficients
// matrix.
let preBias: [Int16] = [0, 0, 0, 0]
let postBias: Int32 = 0
let result = vImageMatrixMultiply_ARGB8888ToPlanar8(
&source,
&destination,
&coefficients,
divisor,
preBias,
postBias,
vImage_Flags(kvImageNoFlags))
guard result == kvImageNoError else { return nil }
defer { free(destination.data) }
// Create a 1-channel, 8-bit grayscale format that's used to
// generate a displayable image.
var monoFormat = vImage_CGImageFormat(
bitsPerComponent: 8,
bitsPerPixel: 8,
colorSpace: Unmanaged.passRetained(CGColorSpaceCreateDeviceGray()),
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue),
version: 0,
decode: nil,
renderingIntent: .defaultIntent)
// Create a Core Graphics image from the grayscale destination buffer.
let cgImage = vImageCreateCGImageFromBuffer(&destination,
&monoFormat,
nil,
nil,
vImage_Flags(kvImageNoFlags),
nil)?.takeRetainedValue()
return cgImage.map { UIImage(cgImage: $0) }
}
func sourceBuffer(for image: UIImage) -> vImage_Buffer? {
guard let cgImage = image.cgImage else { return nil }
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).union(.byteOrder32Big)
var format = vImage_CGImageFormat(bitsPerComponent: 8,
bitsPerPixel: 32,
colorSpace: Unmanaged.passRetained(CGColorSpaceCreateDeviceRGB()),
bitmapInfo: bitmapInfo,
version: 0,
decode: nil,
renderingIntent: .defaultIntent)
var sourceImageBuffer = vImage_Buffer()
vImageBuffer_InitWithCGImage(&sourceImageBuffer,
&format,
nil,
cgImage,
vImage_Flags(kvImageNoFlags))
return sourceImageBuffer
func destinationBuffer(for sourceBuffer: vImage_Buffer) -> vImage_Buffer {
var destinationBuffer = vImage_Buffer()
vImageBuffer_Init(&destinationBuffer,
sourceBuffer.height,
sourceBuffer.width,
8,
vImage_Flags(kvImageNoFlags))
return destinationBuffer
}
How to Upload Image as Binary
I am retrieving image from gallery and taking the name of the image by using below code:
you can use the below function.
func createMultipart(image: UIImage, callback: Bool -> Void){
// use SwiftyJSON to convert a dictionary to JSON
var parameterJSON = JSON([
"id_user": "test"
])
// JSON stringify
let parameterString = parameterJSON.rawString(encoding: NSUTF8StringEncoding, options: nil)
let jsonParameterData = parameterString!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
// convert image to binary
let imageData = UIImageJPEGRepresentation(image, 0.7)
// upload is part of AlamoFire
upload(
.POST,
URLString: "use your url here",
multipartFormData: { multipartFormData in
// fileData: puts it in "files"
multipartFormData.appendBodyPart(fileData: jsonParameterData!, name: "goesIntoFile", fileName: "json.txt", mimeType: "application/json")
multipartFormData.appendBodyPart(fileData: imageData, name: "file", fileName: "ios.jpg", mimeType: "image/jpg")
// data: puts it in "form"
multipartFormData.appendBodyPart(data: jsonParameterData!, name: "goesIntoForm")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, data, error in
let json = JSON(data!)
println("json:: \(json)")
callback(true)
}
case .Failure(let encodingError):
callback(false)
}
}
)
}
let fotoImage = UIImage(named: "foto")
createMultipart(fotoImage!, callback: { success in
if success { }
})
Send image to server as binary data
Firstly you can get an NSData object containing either a PNG or JPEG representation of the image data using the UIImagePNGRepresentation and UIImageJPEGRepresentation functions.
// To get the data from a PNG file
NSData *dataForPNGFile = UIImagePNGRepresentation(yourImage);
// To get the data from a JPEG file
NSData *dataForPNGFile = UIImageJPEGRepresentation(yourImage, 0.9f);
(for more information see: UIImage Class Reference)
To finish to upload data from your iPhone to your server you can do this:
- (void)sendImage {
NSData *postData = [nsdata from your original image];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
// Init and set fields of the URLRequest
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"POST"];
[request setURL:[NSURL URLWithString:[NSString stringWithString:@"http://yoururl.domain"]]];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
// Return data of the request
NSData *receivedData = [[NSMutableData data] retain];
}
[request release];
}
Related Topics
How Is Filters Uiscrollview/Uicollectionview in Apple's Photos App Implemented That It Opens So Fast
Rounding Uiimage and Adding a Border
How to Check Text Field Input at Real Time
How to Sort 1 Array in Swift/Xcode and Reorder Multiple Other Arrays by the Same Keys Changes
Xamarin "The Executable Was Signed with Invalid Entitlements"
Odd Property Declaration Syntax Containing Angular Brackets <>
String Replace Phone Number iOS Swift
Nsurlcache Does Not Clear Stored Responses in iOS8
iOS - Another Thread Needs to Send Reloaddata to the Mainthread
Installing Openssl Library for Xcode
How to Use Nsurlsession to Determine If Resource Has Changed
Swift Framework Does Not Include Symbols from Extensions to Generic Structs
Uialertview Is Not Working in Swift
Core Data Sum of All Instances Attribute
How to Remove Black Edge on Uiimageview with Rounded Corners and a Border Width
How to Apply Audio Effect to a File and Write to Filesystem - iOS