1

プログラムcng2jpg.cで言及されている C 関数 convertCNGFileToJPGFile を変換しようとしているときに行き詰まりました。

私はPerlで同じことを書こうとしてきましたが、hex、pack、unpack関数のノウハウが十分ではありません。

以下で説明するように、誰かが Perl で同様のコードを書くことができれば、本当に感謝しています。

while ((bytesRead = fread(buffer, 1, kBufferSize, inputFile))) {
    if (!isValidCNG) {
        if (bytesRead < 11 || strncmp("\xa5\xa9\xa6\xa9", (char *)(buffer + 6), 4)) {
            fprintf(stderr, "%s does not appear to be a valid CNG file\n", inputFileName);
            return 0;
        }
        isValidCNG = 1;
    }
    for (size_t i = 0; i < bytesRead; i++)
        buffer[i] ^= 0xEF;
    size_t bytesWritten = fwrite(buffer, 1, bytesRead, outputFile);
    if (bytesWritten < bytesRead) {
        fprintf(stderr, "Error writing %s\n", outputFileName);
        return 0;
    }
}

前もって感謝します。

4

1 に答える 1

5

コードを正しく読んでいる場合、(有効性チェック以外に) 実行しているのは、ファイル内の各バイトをバイト 0xEF で XOR することだけです (つまり、各バイトの 5 番目の下位ビットを除くすべてを反転させます)。Perl では、次のように実装できます。

local $/ = \(2**16);  # ignore line breaks, read in 64 kiB chunks
while (<>) {
    $_ ^= "\xEF" x length;
    print;
}

有効性チェックは、出力が実際に有効な JPEG ファイルであることを確認するだけです。具体的には、出力ファイルの 7 番目から 10 番目のバイトにマジック ワードが含まれていることを確認します"JFIF"(これは"\xa5\xa9\xa6\xa9"0xEF と XOR した場合になります)。一般に、実際には CNG ファイルではないファイルに対してこのコードを頻繁に実行することを想定していない限り、後で出力の有効性を確認する方が簡単なので、気にしません。(さらに、デコードされたファイルが実際にExif JPEG 画像であり、"Exif"代わりにマジック ワードが含まれている場合、チェックは失敗します。)

チェックを含めたい場合は、次のようにする必要があります

local $/ = \(2**16);  # ignore line breaks, read in 64 kiB chunks
while (<>) {
    $_ ^= "\xEF" x length;
    die "Not a valid CNG file" if $. == 1 and not /^.{6}(JFIF|Exif)/s;        
    print;
}

Ps。このコードの実行が遅すぎる場合は、次の 2 つの改善策をお勧めします。1) より大きなバッファーを使用し、b) 毎回オンザフライで再構築するのではなく、0xEF バイトのマスクを事前に割り当てます。

local $/ = \(2**20);  # ignore line breaks, read in 1 MiB chunks
my $mask = "\xEF" x $$/;
while (<>) {
    $_ ^= substr($mask, 0, length);
    die "Not a valid CNG file" if $. == 1 and not /^.{6}(JFIF|Exif)/s;        
    print;
}
于 2012-12-24T21:07:27.310 に答える