3

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!

Vladislav Kovalyov
  • 763
  • 10
  • 24
  • A couple comments. First, your loop should go through `i < length - 4` to avoid checking bytes outside your range. Second, check only the first byte. If it doesn't match move on to the next one. Don't check all four bytes every time. – Putz1103 Feb 06 '14 at 15:14
  • No need to memcopy, just use imagedata.bytes, that is a byte pointer into the NSData. – zaph Feb 06 '14 at 15:20
  • Also you don't need to make a copy of the data to do this. – trojanfoe Feb 06 '14 at 15:20
  • 1
    @Putz1103 The posted code does only check 1 byte first. In `C` based languages (including Java and Objective-C), `if` statements use "short circuited" evaluation. Since that expression can only be true if all four parts are true, it returns false as soon as one of the parts is false preventing the other parts from being evaluated. So if `buffer[i] != 'l'` then the other three are not evaluated at all. – rmaddy Feb 06 '14 at 15:22

1 Answers1

8

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;
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thank you, but it doesn't work. iRes always -1. But if I open my image in text editor, I can find row with "link". So maybe I need somehow read imageData in UTF8? – Vladislav Kovalyov Feb 07 '14 at 07:49
  • 1
    @VladislavKovalyov: No. - But the problem is probably that with all the transformations asset->defaultRepresentation->fullscreenImage->UIImageJPEGRepresentation you don't necessarily get the original image data. – Martin R Feb 07 '14 at 08:16
  • then how I can get image data without all this transformations? I didn't found any solutions. – Vladislav Kovalyov Feb 07 '14 at 08:29
  • 1
    @VladislavKovalyov: This might help: http://stackoverflow.com/a/12121605/1187415. - Can you explain why you are looking for the text "link" in the JPEG data? – Martin R Feb 07 '14 at 08:35
  • Image have key "link" in EXIF data, but when I making NSLog dictionary with image EXIF - there is no that key. So I need to find in bytes of image. I hope you understand what I said :) – Vladislav Kovalyov Feb 07 '14 at 08:40
  • @VladislavKovalyov: How did you get the "dictionary with image EXIF"? – Martin R Feb 07 '14 at 08:48
  • I get it from metadata. But it doesn't even matter, because with your help I solved this problem! Thank you! – Vladislav Kovalyov Feb 07 '14 at 08:58