2012-05-11 4 views
4

Я загружаю jpg и png с помощью NSURLRequest. Это работает нормально, но иногда файлы повреждены. Я видел Catching error: Corrupt JPEG data: premature end of data segment и у меня это работает для jpg. Кто-нибудь знает способ сделать то же самое для pngs? т.е. программно проверить, действительны ли данные png ...Обнаружить, если файл PNG поврежден в Objective C

ответ

7

Формат PNG имеет несколько встроенных проверок. Каждый «кусок» имеет проверку CRC32, но для проверки того, что вам нужно будет прочитать полный файл.

Более простая проверка (не безупречная, конечно) должна состоять в том, чтобы прочитать начало и окончание файла.

Первые 8 байтов всегда должны быть следующими (десятичными) значениями { 137, 80, 78, 71, 13, 10, 26, 10 } (ref). В частности, байты от второго до четвертого соответствуют строке ASCII «PNG».

В шестнадцатеричной:

89 50 4e 47 0d 0a 1a 0a 
.. P N G ........... 

Вы также можете проверить последние 12 байт файла (IEND порции). Средние 4 байта должны соответствовать строке ASCII «IEND». Более конкретно последние 12 байт должны быть (в гексе):

00 00 00 00 49 45 4e 44 ae 42 60 82 
........... I E N D ........... 

(Строго говоря, это не совсем обязательно для PNG-файл до конца с этими 12 байтами, сам IEND ломоть сигнализирует конец потока PNG и поэтому файл может в принципе иметь дополнительные байты, которые будут игнорироваться с помощью устройства PNG. На практике это крайне маловероятно).

1

Так же, как и в Catching error: Corrupt JPEG data: premature end of data segment здесь есть фрагмент кода для PNG:

- (BOOL)dataIsValidPNG:(NSData *)data 
{ 
    if (!data || data.length < 12) 
    { 
     return NO; 
    } 

    NSInteger totalBytes = data.length; 
    const char *bytes = (const char *)[data bytes]; 

    return (bytes[0] == (char)0x89 && // PNG 
      bytes[1] == (char)0x50 && 
      bytes[2] == (char)0x4e && 
      bytes[3] == (char)0x47 && 
      bytes[4] == (char)0x0d && 
      bytes[5] == (char)0x0a && 
      bytes[6] == (char)0x1a && 
      bytes[7] == (char)0x0a && 

      bytes[totalBytes - 12] == (char)0x00 && // IEND 
      bytes[totalBytes - 11] == (char)0x00 && 
      bytes[totalBytes - 10] == (char)0x00 && 
      bytes[totalBytes - 9] == (char)0x00 && 
      bytes[totalBytes - 8] == (char)0x49 && 
      bytes[totalBytes - 7] == (char)0x45 && 
      bytes[totalBytes - 6] == (char)0x4e && 
      bytes[totalBytes - 5] == (char)0x44 && 
      bytes[totalBytes - 4] == (char)0xae && 
      bytes[totalBytes - 3] == (char)0x42 && 
      bytes[totalBytes - 2] == (char)0x60 && 
      bytes[totalBytes - 1] == (char)0x82); 
} 
+0

Если использовать memcmp – jjxtra

0

Nicer версия dataIsValidPNG:

BOOL dataIsValidPNG(NSData *data) { 

    if (!data) { 
     return NO; 
    } 

    const NSInteger totalBytes = data.length; 
    const char *bytes = (const char *)[data bytes]; 
    const char start[] = { '\x89', 'P', 'N', 'G', '\r', '\n', '\x1a', '\n' }; 
    const char end[] = { '\0', '\0', '\0', '\0', 'I', 'E', 'N', 'D', '\xAE', 'B', '`', '\x82' }; 

    if (totalBytes < (sizeof(start) + sizeof(end))) { 
     return NO; 
    } 

    return (memcmp(bytes, start, sizeof(start)) == 0) && 
      (memcmp(bytes + (totalBytes - sizeof(end)), end, sizeof(end)) == 0); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^