Reading binary image data from a web service in UIImage

I use a web service in my iPhone application. The web service method returns a response that has several fields (for example, ID, description, etc.). One of these fields contains binary image data that I need to convert to UIImage in my iPhone application.

I have been using NSXMLParser successfully to extract data from an XML response. In the parser:foundCharacters: XMLParser selector, it gives an NSString* pointing to a line inside each field. Since this is a string, this is what I do to read image data when I encounter an image field:

 UIImage *img = [[UIImage alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]; 

But the img variable is still "nil" after this line. It looks like the data from the XML string is not compatible with the conversion. What am I doing wrong here? (I can read other fields in my variables, but not in this image data field)

Thanks in advance.

+4
source share
2 answers

After fbrereto answered, I managed to convert the string to NSData using the sample code at this link: http://www.cocoadev.com/index.pl?BaseSixtyFour (go to the sample code for the user MiloBird). Now I can successfully create the image.

It uses objective-c categories to add the + (id)dataWithBase64EncodedString:(NSString *)string; to the NSData class. Here's the necessary code that I extracted from the link above:

 //MBBase64.h @interface NSData (MBBase64) + (id)dataWithBase64EncodedString:(NSString *)string; // Padding '=' characters are optional. Whitespace is ignored. @end //MBBase64.m static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @implementation NSData (MBBase64) + (id)dataWithBase64EncodedString:(NSString *)string; { if (string == nil) [NSException raise:NSInvalidArgumentException format:nil]; if ([string length] == 0) return [NSData data]; static char *decodingTable = NULL; if (decodingTable == NULL) { decodingTable = malloc(256); if (decodingTable == NULL) return nil; memset(decodingTable, CHAR_MAX, 256); NSUInteger i; for (i = 0; i < 64; i++) decodingTable[(short)encodingTable[i]] = i; } const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding]; if (characters == NULL) // Not an ASCII string! return nil; char *bytes = malloc((([string length] + 3) / 4) * 3); if (bytes == NULL) return nil; NSUInteger length = 0; NSUInteger i = 0; while (YES) { char buffer[4]; short bufferLength; for (bufferLength = 0; bufferLength < 4; i++) { if (characters[i] == '\0') break; if (isspace(characters[i]) || characters[i] == '=') continue; buffer[bufferLength] = decodingTable[(short)characters[i]]; if (buffer[bufferLength++] == CHAR_MAX) // Illegal character! { free(bytes); return nil; } } if (bufferLength == 0) break; if (bufferLength == 1) // At least two characters are needed to produce one byte! { free(bytes); return nil; } // Decode the characters in the buffer to bytes. bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4); if (bufferLength > 2) bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2); if (bufferLength > 3) bytes[length++] = (buffer[2] << 6) | buffer[3]; } realloc(bytes, length); return [NSData dataWithBytesNoCopy:bytes length:length]; } @end 

Thanks everyone!

+5
source

The trick with NSString is that there is an implicit encoding associated with the data it contains. The resulting image will most likely be in a format that will not be correctly converted, since it is either binary data or some encoding without loss of binary data (for example, base64). The trick is to make sure that you do not allow NSString to perform any encoding conversions at all, otherwise your image data will be corrupted. Instead of using dataUsingEncoding: I would try the API more like getBytes:maxLength:usedLength:encoding:options:range:remainingRange . Although more complicated than dataUsingEncoding: I think this will give you the flexibility needed to get only data from NSString and nothing more.

+1
source

Source: https://habr.com/ru/post/1302837/


All Articles