【问题标题】:Jpeglib code gives garbled output, even the bundled example code?Jpeglib 代码给出了乱码输出,即使是捆绑的示例代码?
【发布时间】:2009-02-03 23:38:52
【问题描述】:

我在 Ubuntu Intrepid 上使用 jpeglib62 6b-14。我正在编写一些代码,当我尝试运行它时,它只会在顶部出现一些乱码输出的黑屏。经过几个小时的调试,我把它归结为 JPEG 基础,所以我拿了示例代码,围绕它写了一小段代码,输出完全相同。

我确信 jpeglib 已在该系统的更多地方使用,它只是存储库中的版本,所以我不敢说这是 jpeglib 或 Ubuntu 打包中的错误。

我将示例代码放在下面(大多数 cmets 被剥离)。 输入的JPEG文件是一个未压缩的3通道640x480文件,所以它应该是921600字节(确实如此)。输出图像是JFIF,大约9000字节。

如果您能给我一点提示,我将不胜感激。

谢谢!

#include <stdio.h>
#include <stdlib.h>
#include "jpeglib.h"
#include <setjmp.h>

int main ()
{
  // read data
  FILE *input = fopen("input.jpg", "rb");
  JSAMPLE *image_buffer = (JSAMPLE*) malloc(sizeof(JSAMPLE) * 640 * 480 * 3);
  if(input == NULL or image_buffer == NULL)
    exit(1);
  fread(image_buffer, 640 * 3, 480, input);

  // initialise jpeg library
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);

  // write to foo.jpg
  FILE *outfile = fopen("foo.jpg", "wb");
  if (outfile == NULL)
    exit(1);
  jpeg_stdio_dest(&cinfo, outfile);

  // setup library
  cinfo.image_width = 640;
  cinfo.image_height = 480;
  cinfo.input_components = 3; // 3 components (R, G, B)
  cinfo.in_color_space = JCS_RGB; // RGB
  jpeg_set_defaults(&cinfo); // set defaults

  // start compressing
  int row_stride = 640 * 3; // number of characters in a row
  JSAMPROW row_pointer[1]; // pointer to the current row data
  jpeg_start_compress(&cinfo, TRUE); // start compressing to jpeg

  while (cinfo.next_scanline < cinfo.image_height) {
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  jpeg_finish_compress(&cinfo);

  // clean up
  fclose(outfile);
  jpeg_destroy_compress(&cinfo);
}

【问题讨论】:

    标签: c jpeg libjpeg


    【解决方案1】:

    您正在将 JPEG 文件读入内存(没有解压缩)并写出该缓冲区,就好像它未压缩一样,这就是您得到垃圾的原因。您需要先解压缩图像,然后才能将其输入 JPEG 压缩器。

    换句话说,JPEG 压缩器假定其输入是原始像素。

    您可以使用 ImageMagick 将输入图像转换为原始 RGB:

    convert input.jpg rgb:input.raw
    

    它的大小应该正好是 921600 字节。

    编辑:当您声明您的输入 JPEG 文件为 未压缩 时,您的问题具有误导性。无论如何,我编译了你的代码,它工作正常,正确压缩图像。如果您可以上传您用作输入的文件,则可以进一步调试。如果没有,我建议您使用 ImageMagick 从已知 JPEG 创建的图像来测试您的程序:

    convert some_image_that_is_really_a_jpg.jpg -resize 640x480! rgb:input.jpg
    

    【讨论】:

    • 感谢您的回答,但是:“输入的 JPEG 文件是一个未压缩的 640x480 文件,具有 3 个通道,因此它应该是 921600 字节(确实如此)。”它是未压缩的,大小为 921600 字节!
    • 什么...?当我在原始图像上运行压缩,然后在结果(也是 621600 字节)上运行 jpeginfo 时,我得到“不是 JPEG 文件:以 0x80 0x78 开头”,然后当我在其上运行程序时,我得到一个有效的结果图!这里发生了什么?! :S
    • 结果输入图像是 921600 字节,这是出于某种奇怪的巧合。它有一个 jpeg 标题,所以无论如何都有问题。我现在在重新压缩之前解压缩它(使用 SDL)。谢谢:-)
    【解决方案2】:

    您正在将输入文件读入压缩的内存中,然后在将其重新压缩到文件之前。您需要在再次压缩之前解压缩 image_buffer。或者,而不是在 jpeg 中读取,而是读取 .raw 图像

    【讨论】:

    • 感谢您的回答,但是:“输入的 JPEG 文件是一个未压缩的 640x480 文件,具有 3 个通道,因此它应该是 921600 字节(确实如此)。”它是未压缩的,大小为 921600 字节!
    【解决方案3】:

    “输入的 JPEG 文件是未压缩的”究竟是什么意思? Jpeg 都是压缩的。

    在您的代码中,似乎在循环中您将一行像素提供给 libjpeg 并要求它对其进行压缩。它不是那样工作的。 libjpeg 必须至少有 8 行才能开始压缩(有时甚至更多,取决于参数)。所以最好让 libjpeg 来控制输入缓冲区,不要为它做它的工作。

    我建议您阅读 cjpeg.c 是如何工作的。我认为最简单的方法是将数据放入 libjpeg 已知的原始类型(例如 BMP),然后使用 libjpeg 将 BMP 图像读入其内部表示并从那里压缩。

    【讨论】:

    • 这是来自jpeg示例代码,它应该是这样完成的。并不是所有的 jpeg 都被压缩了——这样,这个 jpeg 就有了现成的原始图像数据,因此大小:640 * 480 * 3,每个单元格每个颜色通道正好一个字节。因此未压缩。
    • 但是,根据上面的回复 - 似乎图像至少有一个 jpeg 标题,它可能不应该有。虽然它仍然是 921600 字节 - 所以可能会有一些压缩。我会写一些解压代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多