I have a question concerning my last post
But I think at first I should provide some code:
This is the function to handle my created object
- (void)handleObject:(NSMutableData *)object {
NSLog(#"[object length] = %d", [object length]);
Byte *byteArray;
byteArray = (Byte *)[object bytes];
switch (byteArray[5]) {
case 0: NSLog(#"Login OK");
break;
case 1: NSLog(#"Exit. Server disconnect");
break;
case 2: NSLog(#"Ping erhalten");
break;
case 4: NSLog(#"Points received");
break;
case 6: NSLog(#"transfer of POLYLINE vector objects");
break;
case 8: NSLog(#"transfer of POLYGON vector objects");
break;
case 9: NSLog(#"transfer of Render Rule");
break;
case 10: {
NSLog(#"end of response for RequestVectorObjects");
isLoading = FALSE;
}
break;
case 11: NSLog(#"Background Colorcode: %d", (byteArray[6] & 0xFF));
break;
default: NSLog(#"From server: default value");
break;
}
}
And I here I receive the data from a stream
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
isLoading = YES;
while (isLoading) {
uint8_t bufSize[4];
int packetLength = 0;
[(NSInputStream *)stream read:bufSize maxLength:4];
packetLength = [self bytesToInt:bufSize withOffset:0];
NSLog(#"packetLength: %d", packetLength);
[tempStore appendBytes:bufSize length:4];
if (packetLength == 25600) {
loggedIn = YES;
uint8_t buf[4];
[(NSInputStream *)stream read:buf maxLength:4];
[tempStore appendBytes:buf length:4];
[self handleObject:tempStore];
}
else {
uint8_t buf[packetLength];
[(NSInputStream *)stream read:buf maxLength:packetLength];
[tempStore appendBytes:buf length:packetLength];
[self handleObject:tempStore];
}
[tempStore resetBytesInRange:NSMakeRange(0, [tempStore length])];
[tempStore setLength:0];
}
NSLog(#"Finished loading objects");
} break;
}
It all works just fine with the simulator or if I debug the application on the iPhone, but if try to run it on the device I always get BAD_EXCESS, because the value of packetLength is wrong and so I try to read too much byte into my buffer.
Now to my question: How can it be that all values are right in debug mode, but get totally messed up in run mode? Is there anything I could to avoid that problem or I should be aware of?
Your help is much appreciated
Here is my BytesToInt Function, but I think it works as it should, if the received values are correct
- (int)bytesToInt:(Byte *)b withOffset:(int)offset {
int ret = 0;
for (int i = 0; i < 4; i++) {
ret |= (b[offset + i] & 0xFF) << (3-i)*8;
}
return ret;
}
I finally did it by looping the received data until I reached my maxLength value. It wasn't too hard to fix, but I wasn't acting quite smart...
Well, here is how I did it:
isLoading = YES;
while (isLoading) {
uint8_t bufSize[4];
int packetLength , maxLength, len;
maxLength = 4;
len = [(NSInputStream *)stream read:bufSize maxLength:maxLength];
NSLog(#"len = %d", len);
packetLength = [self bytesToInt:bufSize withOffset:0];
NSLog(#"packetLength: %d", packetLength);
[tempStore appendBytes:bufSize length:maxLength];
if (packetLength == 25600) {
loggedIn = YES;
maxLength = 4;
uint8_t buf[maxLength];
len = [(NSInputStream *)stream read:buf maxLength:maxLength];
NSLog(#"len = %d", len);
[tempStore appendBytes:buf length:maxLength];
}
else {
maxLength = packetLength;
BOOL allDataReceived = NO;
while (!allDataReceived) {
uint8_t buf[maxLength];
len = [(NSInputStream *)stream read:buf maxLength:maxLength];
NSLog(#"len = %d", len);
if (len < maxLength) {
maxLength -= len;
[tempStore appendBytes:buf length:len];
}
else {
allDataReceived = YES;
[tempStore appendBytes:buf length:len];
}
}
}
[self handleObject:tempStore];
[tempStore resetBytesInRange:NSMakeRange(0, [tempStore length])];
[tempStore setLength:0];
}
Check the return value of your [NSInputStream read]. Specifying maxLength does not mean that actually that many bytes will be really read. It can be less, or even 0. If the stream reads only 2 bytes, I guess you will have to issue a second read with a pointer that points behind the bytes already read in your buffer, and with maxLength of the remaining bytes in the buffer.
Related
I am working on PDF annotation app i added PDF file annotation in iPhone it working fine it annotation also visible any reader but facing one issue How to get EmbeddedFiles from File Attachment Annotation in PDF file whose is created annotation from desktop how can do for this issue
i am using this code for get contents and location of annotation from File Attachment Annotation it working fine
CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(pPage);
// NSLog(#"%#",(NSDictionary*)pageDictionary);
CGPDFArrayRef outputArray;
if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &outputArray)) {
[pdfAnnots release];
return nil;
}
CGPDFArrayRef rectArray;
if(!CGPDFDictionaryGetArray(annotDict, "Rect", &rectArray)) {
break;
}
int arrayCount = CGPDFArrayGetCount( rectArray );
CGPDFReal coords[4];
for( int k = 0; k < arrayCount; ++k ) {
CGPDFObjectRef rectObj;
if(!CGPDFArrayGetObject(rectArray, k, &rectObj)) {
break;
}
CGPDFReal coord;
if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &coord)) {
break;
}
coords[k] = coord;
}
CGRect rect = CGRectMake(coords[0],coords[1],coords[2],coords[3]);
NSLog(#"%#",NSStringFromCGRect(rect));
CGPDFDictionaryRef aDict;
if(CGPDFDictionaryGetDictionary(annotDict, "AP", &aDict))
{
CGPDFStreamRef textStringRef33;
if(CGPDFDictionaryGetStream(aDict, "N", &textStringRef33)) {
CGPDFDataFormat *format = NULL;
CFDataRef contdata = CGPDFStreamCopyData( textStringRef33, format );
NSData *data=(NSData*)contdata;
}
please help me
Thank you in advance
PDF embeds is not the same as annotations. Embedded files stored in document section instead of page section.
Annonation can contains embedded file, but mechanism of it's extraction is different.
First, you should see internal structure of annotation object. You can use function like this:
static void op_Applier(const char *key, CGPDFObjectRef value, void *info) {
if (*(int *)info > 6) {
return;
}
const char *valuestr = NULL;
CGPDFObjectType type = CGPDFObjectGetType(value);
int i = 0;
for (i = 0; i < *(int *)info; i++) {
printf("\t");
}
printf("%s", key);
switch (type) {
case kCGPDFObjectTypeBoolean: {
bool b;
CGPDFObjectGetValue(value, type, &b);
printf(" (boolean) : %s\n", (b)?"true":"false");
}
break;
case kCGPDFObjectTypeInteger: {
int64_t i;
CGPDFObjectGetValue(value, type, &i);
printf(" (integer) : %lld\n", i);
}
break;
case kCGPDFObjectTypeReal: {
CGPDFReal f;
CGPDFObjectGetValue(value, type, &f);
printf(" (real) : %f\n", f);
}
break;
case kCGPDFObjectTypeName:{
CGPDFObjectGetValue(value, type, (void *)&valuestr);
printf(" (name) : %s\n", valuestr);
}
break;
case kCGPDFObjectTypeString: {
CGPDFStringRef str;
CGPDFObjectGetValue(value, type, &str);
printf(" (string) : %s\n", CGPDFStringGetBytePtr(str));
}
break;
case kCGPDFObjectTypeArray: {
printf(" (array)\n");
CGPDFArrayRef arr;
CGPDFObjectGetValue(value, type, &arr);
int t = *(int *)info + 1;
int j;
size_t size = CGPDFArrayGetCount(arr);
for (j = 0; j < size; j ++) {
CGPDFObjectRef obj;
CGPDFArrayGetObject(arr, j, &obj);
char buf[4] = {0};
sprintf(buf, "%d", j);
op_Applier(buf, obj, &t);
}
}
break;
case kCGPDFObjectTypeDictionary: {
printf(" (dictionary)\n");
CGPDFDictionaryRef dict;
CGPDFObjectGetValue(value, type, &dict);
int t = *(int *)info + 1;
CGPDFDictionaryApplyFunction(dict, &op_Applier, &t);
}
break;
case kCGPDFObjectTypeStream:
printf(" (stream)\n");
break;
default:
printf(" (NULL)\n");
break;
}
}
int t = 0; op_Applier("MyDictionary", yourAnnotationDictionary, &t);
Second, you should find path to your file (it will be stream object), and move to this object. This can be done with CGPDFDictionary methods.
Third, get NSData from stream, and save it
CGPDFDataFormat format;
CFDataRef data = CGPDFStreamCopyData(stream, &format);
[((__bridge NSData *)data) writeToURL:resultUrl atomically:NO];
CFRelease(data);
P.S. PostScript syntax of PDF annotation can be different. Different libraries use different syntax, and you should implement all possibilities to make app, that works on almost all PDF files. Sample can be found in this file in vfr Reader
I am currently working on an app which uses a live stream from an IP camera(PnP IP/Network camera manufactured by V Star). When connected using the Api provided I get the frame o/p as PBFrames. I am having trouble displaying them. anybody who have been through it please help. Thanks in advance
void *thread_ReceiveVideo(void *arg)
{
NSLog(#"[thread_ReceiveVideo] Starting...");
int avIndex = *(int *)arg;
char *buf = malloc(VIDEO_BUF_SIZE);
unsigned int frmNo;
int ret;
FRAMEINFO_t frameInfo;
while (1)
{
ret = avRecvFrameData(avIndex, buf, VIDEO_BUF_SIZE, (char *)&frameInfo, sizeof(FRAMEINFO_t), &frmNo);
if(ret == AV_ER_DATA_NOREADY)
{
usleep(30000);
continue;
}
else if(ret == AV_ER_LOSED_THIS_FRAME)
{
NSLog(#"Lost video frame NO[%d]", frmNo);
continue;
}
else if(ret == AV_ER_INCOMPLETE_FRAME)
{
NSLog(#"Incomplete video frame NO[%d]", frmNo);
NSLog(#" the biffer is : %lu",sizeof(buf));
continue;
}
else if(ret == AV_ER_SESSION_CLOSE_BY_REMOTE)
{
NSLog(#"[thread_ReceiveVideo] AV_ER_SESSION_CLOSE_BY_REMOTE");
break;
}
else if(ret == AV_ER_REMOTE_TIMEOUT_DISCONNECT)
{
NSLog(#"[thread_ReceiveVideo] AV_ER_REMOTE_TIMEOUT_DISCONNECT");
break;
}
else if(ret == IOTC_ER_INVALID_SID)
{
NSLog(#"[thread_ReceiveVideo] Session cant be used anymore");
break;
}
NSLog(#"FRAM INFO FLAG :%hhu ",frameInfo.flags);
if(frameInfo.flags == IPC_FRAME_FLAG_PBFRAME)
{
// got an PBFrame, draw it.
NSLog(#"got a video iframe to display");
// NSString *iFramestring = [NSString stringWithUTF8String:buf];
printf("correclty recieved frame is %s",buf);
//
}
}
free(buf);
NSLog(#"[thread_ReceiveVideo] thread exit");
return 0;
}
I am trying to decompress data using the ZLib in iPhone, but it always through error of "Invalid header Check".
To compress the data I am using the following in Java
Implementation: Standard Java implementation for Zlib
Deflator : java.util.zip.Deflater
version 1.45, 04/07/06
Compression level: BEST_COMPRESSION
In iPhone the following is the code for decompressing:
- (NSData *)zlibInflate
{
if ([self length] == 0) return self;
unsigned full_length = [self length];
unsigned half_length = [self length] / 2;
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[self bytes];
strm.avail_in = [self length];
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
if (inflateInit (&strm) != Z_OK) return nil;
while (!done)
{
// Make sure we have enough room and reset the lengths.
if (strm.total_out >= [decompressed length])
[decompressed increaseLengthBy: half_length];
strm.next_out = [decompressed mutableBytes] + strm.total_out;
strm.avail_out = [decompressed length] - strm.total_out;
// Inflate another chunk.
status = inflate (&strm, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) done = YES;
else if (status != Z_OK) {
NSLog(#"%s", strm.msg);
break;
}
}
if (inflateEnd (&strm) != Z_OK) return nil;
// Set real length.
if (done)
{
[decompressed setLength: strm.total_out];
return [NSData dataWithData: decompressed];
}
else return nil;
}
Following is a sample compressed string:
xÚÝUko²Jþ~?ó?¥¾?¤?©?´ÚjCMX,Òµ?ª?µßVX¹È?¿.øë_?¯¶ZÏ%íùxHH&Ã<ÏÌ3ÌÎ
#2.ðE?ºqþpéEzÏ09IoÒ?ª? ?®?£àÌönì$brÛ#fl95?¿»a//Tçáò?¢?¿½
µ©ÊÃÉPÔ¼:8y¦ý.äÎ?µ?¥?¼y?©ã¯9ö?¥½?¢±ÝûwÛ?§ãga?©á8?¨?m\Õ?»6,'Îe?¬}(L}7ÆÅ6#gJ(¥7´s?¬d.ó,Ë°¦prßýÕÖ?
Below is the function for compresser:
public static byte[] compress(String s) {
Deflater comp = new Deflater();
//comp.setLevel(Deflater.BEST_COMPRESSION);
comp.setInput(s.getBytes());
comp.finish();
ByteArrayOutputStream bos = new ByteArrayOutputStream(s.length());
// Compress the data
byte[] buf = new byte[1024];
try {
while (!comp.finished()) {
int count = comp.deflate(buf);
bos.write(buf, 0, count);
}
bos.close();
} catch (Exception e) {
//Log.d(TAG, e.getMessage());
e.printStackTrace();
}
// Get the compressed data
byte[] compressedData = bos.toByteArray();
// put in this fix for Symbol scanners
byte[] compressedDataForSymbol = mungeForSymbol(compressedData);
/*
* byte[] decompressedDataForSymbol =
* decompressedDataAfterSymbol(compressedDataForSymbol); // check they
* are the same for(int i=0;i<compressedData.length;i++) { if
* (compressedData[i] != decompressedDataForSymbol[i]) {
* //System.out.println("Error at " + i); } }
*/
return compressedDataForSymbol;
// return s.getBytes();
}
Using Java Deflater with default compression level creates output encoded data with header with first two bytes 0x78 0x9c. These are not used in IOS. Just remove the first two bytes and try the Inflate ie decompression in IOS. It should work.
I had faced the same issue, But i wanted data from IOS(compressed) to android(decompressed).
I am trying to receive a jpeg image from my c# server. The weird thing is when I run it with the debugger and have a break point anywhere in the method it works perfectly fine. Without a breakpoint then I get this error
Corrupt JPEG data: premature end of data segment
Here is my code
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
NSMutableData *data;
data = [NSMutableData new];
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
uint8_t buffer[1024];
int len;
while([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
[data appendBytes:(const void*)buffer length:sizeof(buffer)];
}
}
UIImage *images = [[UIImage alloc]initWithData:data];
[dvdCover setImage:images];
} break;
case NSStreamEventEndEncountered:
{
//UIImage *images = [[UIImage alloc]initWithData:data];
//[dvdCover setImage:images];
} break;
}
}
hi you can check this code hop it will help you...
case NSStreamEventHasBytesAvailable:
{
uint32_t max_size = 1000000; // Max size of the received imaged you can modify it as your reqirement.
NSMutableData* buffer = [[NSMutableData alloc] initWithLength: max_size];
NSInteger totalBytesRead = 0;
NSInteger bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] maxLength: max_size];
if (bytesRead != 0) {
while (bytesRead > 0 && totalBytesRead + bytesRead < max_size) {
totalBytesRead+= bytesRead;
bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] + totalBytesRead maxLength: max_size - totalBytesRead];
}
if (bytesRead >= 0) {
totalBytesRead += bytesRead;
}
else {
// read failure, report error and bail (not forgetting to release buffer)
}
[buffer setLength: totalBytesRead];
yourImageName.image = [UIImage imageWithData: buffer];
[buffer release];
} break;
It seems you are assuming the whole JPEG image will be transferred in one chunk, and you can just read it with one occurence of 'HasBytesAvailable' event. However you should also consider the case where the JPEG image is transferred to you in multiple chunks.
It might work for you if you set breakpoint, because your code execution might be halted somewhere, and your network buffer had plenty time to receive all bytes of the image. But without breakpoints it might not have time to do so.
Try refactoring your code to accumulate the bytes chunk, and only assume it's done when all bytes have been transferred. (Normally you have to know beforehand how many bytes the image is going to be -- or you can just capture the end of stream event)
I'm programming a client on the iPhone. I want to send some strings, and receive an image from the server.
I found this tutorial (http://www.devx.com/wireless/Article/43551), it has been very useful. It works if I want to receive strings, but now I want to receive an image, and I can't make it work.
This is my code when the iPhone receives data. It's a mix made with the tutorial and this answer from JeremyP (http://stackoverflow.com/questions/4613218):
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable: {
if (data == nil) {
data = [[NSMutableData alloc] init];
}
uint8_t buf[102400];
unsigned int len = 0;
len = [(NSInputStream *)stream read:buf maxLength:102400];
if(len) {
[data appendBytes:(const void *)buf length:len];
// Recibir img
uint8_t size; // Let's make sure size is an explicit width.
NSInteger totalBytesRead = 0;
NSInteger bytesRead = [iStream read: &size maxLength: sizeof size];
while (bytesRead > 0 && totalBytesRead + bytesRead < sizeof size) {
totalBytesRead+= bytesRead;
bytesRead = [iStream read: &size + totalBytesRead maxLength: (sizeof size) - totalBytesRead];
}
if (bytesRead >= 0) {
totalBytesRead += bytesRead;
}
else {
// read failure, report error and bail
}
if (totalBytesRead < sizeof size) {
// connection closed before we got the whole size, report and bail
}
size = ntohl(size); // assume wire protocol uses network byte ordering
NSMutableData* buffer = [[NSMutableData alloc] initWithLength: size];
totalBytesRead = 0;
bytesRead = [iStream read: [buffer mutableBytes] maxLength: size];
while (bytesRead > 0 && totalBytesRead + bytesRead < size) {
totalBytesRead+= bytesRead;
bytesRead = [iStream read: [buffer mutableBytes] + totalBytesRead maxLength: size - totalBytesRead];
}
if (bytesRead >= 0) {
totalBytesRead += bytesRead;
}
else {
// read failure, report error and bail (not forgetting to release buffer)
}
if (totalBytesRead < size) {
// connection closed before we got the whole image, report and bail (not forgetting to release buffer)
}
else {
[buffer setLength: size];
}
imgResultado.image = [UIImage imageWithData: buffer];
[buffer release];
[data release];
data = nil;
}
else {
NSLog(#"No data.");
}
} break;
}}
It doesn't work... could you help me?
Well, I made it work this way, but I'm no sure if there's a better way.
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
uint32_t max_size = 1000000; // Max size of the received imaged.
NSMutableData* buffer = [[NSMutableData alloc] initWithLength: max_size];
NSInteger totalBytesRead = 0;
NSInteger bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] maxLength: max_size];
if (bytesRead != 0) {
while (bytesRead > 0 && totalBytesRead + bytesRead < max_size) {
totalBytesRead+= bytesRead;
bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] + totalBytesRead maxLength: max_size - totalBytesRead];
}
if (bytesRead >= 0) {
totalBytesRead += bytesRead;
}
else {
// read failure, report error and bail (not forgetting to release buffer)
}
[buffer setLength: totalBytesRead];
imgResultado.image = [UIImage imageWithData: buffer];
[buffer release];
}
} break;
}}
With this method, the received image must be smaller than max_size.
If you know a better way to do this, please let me know! ;)
If all you want to do is download an image from the server to display, take a look at this:
https://github.com/michaelkamprath/iPhoneMK/tree/master/Views/MKNetworkImageView
There are a lot of built in functions to the iOS that will handle image downloading for you. That is, if you can encapsulate the entities you want to download as separate URLs (e.g., a web server).
If, however, you are trying to send and receive data across the same TCP connection, I would strongly advise that you change to a more RESTful approach. Partly because it is easier to implement from the client side, partly because you don't have to worry (as much) about the underlying TCP connection.