2012-05-11 8 views
4

NSURLRequestを使用してjpgsとpngsをダウンロードしています。これは正常に動作しますが、ファイルが壊れていることがあります。 私はCatching error: Corrupt JPEG data: premature end of data segmentを見て、これはjpgsのために働いている。 誰かがpngのために同じことをする方法を知っていますか?つまり、PNGデータが有効かどうかをプログラムで確認します。Objective CでPNGファイルが破損しているかどうかを検出します

答えて

7

PNG形式にはいくつかのチェックが組み込まれています。各 "チャンク"にはCRC32のチェックがありますが、フルファイルを読む必要があるかどうかチェックしてください。

さらに基本的なチェック(もちろん簡単ではありません)は、ファイルの開始と終了を読み取ることです。

最初の8バイトは常に次の(10進)値{ 137, 80, 78, 71, 13, 10, 26, 10 }ref)です。特に、2番目から4番目のバイトはASCII文字列 "PNG"に対応しています。進で

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

また、ファイル(IENDチャンク)の最後の12のバイトを確認することができます。中間の4バイトは、ASCII文字列 "IEND"に対応する必要があります。具体的には、最後の12のバイトは、(ヘキサに)する必要があります:

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

(厳密に言えば、それはそれらの12バイトで終了するPNGファイルのために実際に必須ではない、IENDチャンク自体はPNGストリームの終わりを知らせるていますしたがって、ファイルには原則として余分な末尾のバイトがあり、これはPNGリーダーによって無視される可能性がありますが、実際にはこれは非常に不可能です)。

1

PNGのためのコードスニペットであるだけで、ここでCatching error: Corrupt JPEG data: premature end of data segmentのように:dataIsValidPNGの

- (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

よりよいバージョン:

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); 
} 
関連する問題