I am trying to retrieve Base64 string from iOS UIImagePickerController selected event as follows.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
//on selected
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imgData = UIImageJPEGRepresentation(image, 1.0);
NSString *imageString = [[NSString alloc] initWithBytes: [imgData bytes] length:[imgData length] encoding:NSUTF8StringEncoding];
//NSLog(#"Image Data: %#", imageString); it returns Nothing except "Image Data: "
[picker dismissModalViewControllerAnimated:YES];
[picker.view removeFromSuperview];
[picker release];
}
+ (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}
Related
I am getting an json from server in ios which returns one of the value as datatype byte[], I am receiving like
NSData *imageData =[receivedData objectForKey:#"img1"];
if I print this in iOS using NSLog it shows something like below :
(
"-1",
"-40",
"-1",
"-32",
0,
16,
74,
70,
73,
70,
0,
1,
2,
1,
0,
72,
0,
72,
0,
0,
"-1",
"-31",
20,
"-79",
69,
120,
105,
102,
0,
0,
77,
77,
0,
42,
0,
0,
0,
8,
0,
7,
1,
18,
0,
3,
0,
0,
0,
1,
0,
1,
0,
0,
1,
26,
0,
5,
0,
0,
0,
1,
0,
0,
0,
98,
1,
27,
0,
5,
....)
As showing some of the values is showing with double quotes is that the issue? As this is working fine at web application , just need to show this array as image in iOS ?I have to show the image in iOS using the byte array coming from server.
Can anybody point the issue I am new to iOS ..?
Try this.
NSArray *byteArrayReceived = [receivedData objectForKey:#"img1"];
unsigned c = byteArrayReceived.count;
uint8_t *bytes = malloc(sizeof(*bytes) * c);
unsigned i;
for (i = 0; i < c; i++)
{
NSString *str = [byteArrayReceived objectAtIndex:i];
int byte = [str intValue];
bytes[i] = (uint8_t)byte;
}
NSData *data = [NSData dataWithBytes:bytes length:c];
UIImage *image = [UIImage imageWithData:data];
Add this code:
NSArray *array = [receivedData objectForKey:#"img1"];
unsigned c = array.count;
uint8_t *bytes = malloc(sizeof(*bytes) * c);
unsigned i;
for (i = 0; i < c; i++)
{
NSString *str = [array objectAtIndex:i];
int byte = [str intValue];
bytes[i] = byte;
}
NSData *imageData =[NSData dataWithBytesNoCopy:bytes length:c freeWhenDone:YES];// your imageData
UIImage *img=[UIImage imageWithData:data]; // your image
[yourImageView setImage:img];// set to imageView
First you need to convert image data into Base64String.
Make a category of NSData and write code for converting string to base 64
#define BINARY_UNIT_SIZE 3
#define BASE64_UNIT_SIZE 4
void *Base64Decode(
const char *inputBuffer,
size_t length,
size_t *outputLength)
{
if (length == -1)
{
length = strlen(inputBuffer);
}
size_t outputBufferSize = ((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;unsigned char *outputBuffer = (unsigned char*)malloc(outputBufferSize);
size_t i = 0;
size_t j = 0;
while (i < length)
{
unsigned char accumulated[BASE64_UNIT_SIZE];
size_t accumulateIndex = 0;
while (i < length)
{
unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
if (decode != xx)
{
accumulated[accumulateIndex] = decode;
accumulateIndex++;
if (accumulateIndex == BASE64_UNIT_SIZE)
{
break;
}
}
}
if(accumulateIndex >= 2)
outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
if(accumulateIndex >= 3)
outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
if(accumulateIndex >= 4)
outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
j += accumulateIndex - 1;
}
if (outputLength)
{
*outputLength = j;
}
return outputBuffer;
}
// Convert string to base64String
+ (NSData *)dataFromBase64String:(NSString *)aString
{
NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
size_t outputLength;
void *outputBuffer = Base64Decode([data bytes], [data length], &outputLength);
NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
free(outputBuffer);
return result;
}
// now write this code and convert nsdata to image
NSData* data = [NSData dataFromBase64String:[receivedData objectForKey:#"img1"];];
UIImage* image = [UIImage imageWithData:data];
NSLog(#"Image --- %#", image);
Try this.. Hopefully it helps you.. Thanks
i am developing app related to bluetooth my iOS device act as a central and watch act as a peripheral.In order to get some response from the watch i need to give some commands to the watch so that it gives info back i have written the following code
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:
(CBCharacteristic *)characteristic error:(NSError *)error
{
NSString *characteristicUUIDstring = TRANSFER_CHARACTERISTIC_UUID;
CBUUID *characteristicUUID = [CBUUID
UUIDWithString:characteristicUUIDstring];
int comm[6];
comm[0]=0x01;
comm[1]=6;
comm[2]=0x53;
comm[3]=0x00;
comm[4]=0xFFFF;
comm[5]=0xFFFF;
NSMutableArray *arr=[[NSMutableArray alloc]initWithCapacity:4];
for (int i = 0; i < 4; i++) {
NSNumber *number = [NSNumber numberWithFloat:comm[i]];
[arr addObject:number];
}
NSLog(#"mutable arr is %#",arr);
NSString *error1;
NSData *dataarr = [NSPropertyListSerialization dataFromPropertyList:arr
format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error1];
NSUInteger len = [dataarr length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [dataarr bytes], len);
short crc = (short) 0xFFFF;
for (int j = 0; j < [arr count]; j++)
{
Byte c = arr[j];
for (int i = 7; i >= 0; i--)
{
BOOL c15 = ((crc >> 15 & 1) == 1);
BOOL bit = ((c >> (7 - i) & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
{
crc ^= 0x1021; }
}
}
int crc2 = crc - 0xffff0000;
byteData[0] = (Byte) (crc2 % 256);
byteData[1] = (Byte) (crc2 / 256);
NSLog(#"byte data 1is %hhu",byteData[0]);
NSLog(#"byte data 2is %hhu",byteData[1]);
int com[6];
com[0]=0x01;
com[1]=6;
com[2]=0x53;
com[3]=0x00;
com[4]=byteData[0];
com[5]=byteData[1];
NSMutableArray *sendarr=[[NSMutableArray alloc]initWithCapacity:6];
for (int i = 0; i < 6; i++) {
NSNumber *number = [NSNumber numberWithFloat:comm[i]];
[sendarr addObject:number];
}
NSLog(#"mutable arr is %#",sendarr);
// NSData *data = [NSData datawith:&dataByte length:1];
CBMutableCharacteristic *testCharacteristic =
[[CBMutableCharacteristic alloc] initWithType:characteristicUUID
properties:CBCharacteristicPropertyRead|CBCharacteristicPropertyWrite
value:sendarr
permissions:CBAttributePermissionsReadable|CBAttributePermissionsWriteable];
NSLog(#"Read or Write %# ",testCharacteristic);
[peripheral writeValue:dataarr forCharacteristic:testCharacteristic
type:CBCharacteristicWriteWithResponse];
}
I have a jpg image which I am converting to data using the UIImageJPEGRepresentation function
I am then sending the data to a server online and getting it back when it is needed though I get this string:
<ffd8ffe0 00104a46 49460001 01000001 00010000 ffe10058 45786966 00004d4d...>
And I don't know how to convert it back to an image
Thanks in advance
I managed to find a way to do it by converting the string to a base64 string like this:
+ (NSString *) encodeToBase64:(NSData *) rawBytes {
return [StringMethods encodeToBase64:(const uint8_t*) rawBytes.bytes length:rawBytes.length];
}
+ (NSString *) encodeToBase64:(const uint8_t *)input length:(NSInteger) length {
NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *output = (uint8_t *)data.mutableBytes;
for (NSInteger i = 0; i < length; i += 3) {
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = encodingTable[(value >> 18) & 0x3F];
output[index + 1] = encodingTable[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6) & 0x3F] : '=';
output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
Then I saved it onto the server then when loading back in I used this function:
- (NSData *)base64DataFromString: (NSString *)string {
unsigned long ixtext, lentext;
unsigned char ch, inbuf[4], outbuf[3];
short i, ixinbuf;
Boolean flignore, flendtext = false;
const unsigned char *tempcstring;
NSMutableData *theData;
if (string == nil){
return [NSData data];
}
ixtext = 0;
tempcstring = (const unsigned char *)[string UTF8String];
lentext = [string length];
theData = [NSMutableData dataWithCapacity: lentext];
ixinbuf = 0;
while (true) {
if (ixtext >= lentext) {
break;
}
ch = tempcstring [ixtext++];
flignore = false;
if ((ch >= 'A') && (ch <= 'Z')) {
ch = ch - 'A';
} else if ((ch >= 'a') && (ch <= 'z')) {
ch = ch - 'a' + 26;
} else if ((ch >= '0') && (ch <= '9')) {
ch = ch - '0' + 52;
} else if (ch == '+') {
ch = 62;
} else if (ch == '=') {
flendtext = true;
} else if (ch == '/') {
ch = 63;
} else {
flignore = true;
}
if (!flignore) {
short ctcharsinbuf = 3;
Boolean flbreak = false;
if (flendtext) {
if (ixinbuf == 0) {
break;
}
if ((ixinbuf == 1) || (ixinbuf == 2)) {
ctcharsinbuf = 1;
} else {
ctcharsinbuf = 2;
}
ixinbuf = 3;
flbreak = true;
}
inbuf [ixinbuf++] = ch;
if (ixinbuf == 4) {
ixinbuf = 0;
outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);
for (i = 0; i < ctcharsinbuf; i++) {
[theData appendBytes: &outbuf[i] length: 1];
}
}
if (flbreak) {
break;
}
}
}
return theData;
}
And finally to convert it into an image I was this simple method:
UIImage *image = [UIImage imageWithData:imageData];
Is what you are showing a string, or is that what you get when you display NSData? I believe that if you log binary data, it comes out as you've shown.
What you have shown is hexadecimal data, not base64, as the other poster suggested.
You could either write code that uses sscanf() to pull out int values from your hex string, or create an NSScanner object and use it's scanHexInt method. If you google "convert hex NSString to integer" you should find both approaches.
Since your values have spaces between them, NSScanner might be your best bet.
Issue
You are sending NSData to server not NSString, and that's why you are getting this NSData on that format read by you as NSString.
Solution
First you need to send it correctly as NSString to server by doing this:
NSData *imageData= UIImagePNGRepresentation(yourImage);
NSString *encodedString = [imageData base64EncodedStringWithOptions:0];
After you send it to NSString, now you get it back an manipulate it like this. I am using NSData Base64 library to perform this task.
You just manually copy these files to your project. Import the classes to your project and these lines to your code:
#import "NSData+Base64.h"
//This function converts your base64string (NSString Class) to NSData
NSData *data = [[NSData alloc] initWithData:[NSData dataFromBase64String:base64String]];
//Here is where you convert it to UIImage
UIImage *image = [UIImage imageWithData:data];
P.S You can also follow your answer, which to me seems correct, but I just wanted to let you know where were you doing wrong.
This seems to be a good answer for converting:
NSData *dataImage = [[NSData alloc] init];
dataImage = UIImagePNGRepresentation(image);
NSString *stringImage = [dataImage base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
which you can find here:NSString to UIImage
I need to find the sequence of bytes in my image data. I have next code on java, but I need make the same in obj-c.
Java:
private static int searchInBuffer(byte[] pBuf, int iBufferLen) {
for(int i = 0; i<iBufferLen - 7; i++) {
if (pBuf[i] == 'l' && pBuf[i + 1] == 'i' && pBuf[i + 2] == 'n' && pBuf[i + 3] == 'k')
return (int)pBuf[i + 4];
}
return -1;
}
public static int checkFlagInJpeg(String pFullFileName) {
int iRes = -1;
try {
File f = new File(pFullFileName);
FileInputStream is = new FileInputStream(f);
int iBufferSize = 6 * 1024, iCount = 15;
byte buf[] = new byte[iBufferSize];
while((is.available() > 0) && (iCount >= 0)) {
int iRead = is.read(buf),
iFlag = searchInBuffer(buf, iRead);
if (iFlag > 0) {
iRes = iFlag;
break;
}
iCount--;
}
is.close();
}
}
Obj-C (my version):
UIImage *image = [UIImage imageWithCGImage:[[[self.assets objectAtIndex:indexPath.row] defaultRepresentation] fullScreenImage]];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0f);
NSUInteger length = MIN(6*1024, [imageData length]);
Byte *buffer = (Byte *)malloc(length);
memcpy(buffer, [imageData bytes], length);
for (int i=0; i < length - 1; i++) {
if (buffer[i] == 'l' && buffer[i + 1] == 'i' && buffer[i + 2] == 'n' && buffer[i + 3] == 'k')
NSLog(#"%c", buffer[i + 4]);
}
free(buffer);
I'm still not sure, that I understand all aspects of work with bytes, so I need a help.
UPDATE:
The problem was in getting image data. With help of Martin R. I combine to solutions in one and get next working code:
ALAssetRepresentation *repr = [[self.assets objectAtIndex:indexPath.row] defaultRepresentation];
NSUInteger size = (NSUInteger) repr.size;
NSMutableData *data = [NSMutableData dataWithLength:size];
NSError *error;
[repr getBytes:data.mutableBytes fromOffset:0 length:size error:&error];
NSData *pattern = [#"link" dataUsingEncoding:NSUTF8StringEncoding];
NSRange range = [data rangeOfData:pattern options:0 range:NSMakeRange(0, data.length)];
int iRes = -1;
if (range.location != NSNotFound) {
uint8_t flag;
[data getBytes:&flag range:NSMakeRange(range.location + range.length, 1)];
iRes = flag;
}
NSLog(#"%i", iRes);
It's working perfect! Thank you again!
NSData has a method rangeOfData:... which you can use to find the pattern:
NSData *pattern = [#"link" dataUsingEncoding:NSUTF8StringEncoding];
NSRange range = [imageData rangeOfData:pattern options:0 range:NSMakeRange(0, imageData.length)];
If the pattern was found, get the next byte:
int iRes = -1;
if (range.location != NSNotFound && range.location + range.length < imageData.length) {
uint8_t flag;
[imageData getBytes:&flag range:NSMakeRange(range.location + range.length, 1)];
iRes = flag;
}
There are CLLocation2D points, MKMapPoints, MKCoordinates, and convertCoordinate:toPointInView: which all give you points in one form or another. I am drawing a custom route in:
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
Whats the proper point to use for drawing?
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, mapView.frame.size.width, mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
And
-(void) updateRouteView {
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 4.0);
for(int i = 0; i < self.routes.count; i++) {
CLLocation* location = [self.routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
You can use google api like-
Define approirate variable in .h-
NSArray *arrRoutePoints;
MKPolygon *objpolygon;
MKPolyline *objpolyline;
Call function like where you want -
self.arrRoutePoints=[self getRoutePointFrom:newSource to:newDestination];
[self drawRoute];
Function Code :
- (NSArray*)getRoutePointFrom:(MKPointAnnotation *)origin to:(MKPointAnnotation *)destination
{
NSString *saddress=[NSString stringWithFormat:#"%f,%f",origin.coordinate.latitude,origin.coordinate.longitude];
NSString *daddress=[NSString stringWithFormat:#"%f,%f",destination.coordinate.latitude,destination.coordinate.longitude];
NSString *apiUrlString=[NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddress, daddress];
NSURL *apiUrl=[NSURL URLWithString:apiUrlString];
NSError *error;
NSString *apiResponse=[NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSRange range;
range=[apiResponse rangeOfString:#"points:\\\"([^\\\"]*)\\\"" options:NSRegularExpressionSearch];
NSString *encodedPoint=[apiResponse substringWithRange:range];
NSLog(#"Encode lentgh %d",[encodedPoint length]);
encodedPoint=[encodedPoint stringByReplacingOccurrencesOfString:#"points:\"" withString:#""];
encodedPoint=[encodedPoint stringByReplacingOccurrencesOfString:#"\"" withString:#""];
return [self decodePolyLine:[encodedPoint mutableCopy]];
}
- (NSMutableArray *)decodePolyLine:(NSMutableString *)encodedString
{
[encodedString replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encodedString length])];
NSInteger len = [encodedString length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encodedString characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
if(index<len)
{
b = [encodedString characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
}
else
{
break;
}
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
printf("\n[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
- (void)drawRoute
{
int numPoints=[arrRoutePoints count];
if(numPoints >1)
{
CLLocationCoordinate2D *coord=malloc(numPoints *sizeof(CLLocationCoordinate2D));
for(int i=0;i<numPoints;i++)
{
CLLocation *current=[arrRoutePoints objectAtIndex:i];
NSLog(#"%#",[arrRoutePoints objectAtIndex:i]);
NSLog(#"Current \n[%g",current.coordinate.latitude);
NSLog(#"%g]",current.coordinate.longitude);
coord[i]=current.coordinate;
NSLog(#"\n[%g",coord[i].latitude);
NSLog(#"%g]",coord[i].longitude);
}
self.objpolyline=[MKPolyline polylineWithCoordinates:coord count:numPoints];
free(coord);
[mapView addOverlay:objpolyline];
[mapView setNeedsDisplay];
}
}