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 进行异或运算(即翻转除每个字节的第五个最低位之外的所有位)。在 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 异或时会变成魔法字)。通常,除非您希望经常在实际上不是 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;
}

附言。如果此代码运行速度太慢,我建议进行两个可能的改进: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 回答