2

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

我确信 jpeglib 在这个系统上的更多地方使用,它只是存储库中的版本,所以我很犹豫说这是 jpeglib 或 Ubuntu 打包中的错误。

我把示例代码放在下面(大部分评论被删除)。输入的 JPEG 文件是一个未压缩的 640x480 文件,有 3 个通道,所以它应该是 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);
}
4

3 回答 3

2

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

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

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

convert input.jpg rgb:input.raw

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

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

convert some_image_that_is_really_a_jpg.jpg -resize 640x480! rgb:input.jpg
于 2009-02-04T00:00:28.270 回答
1

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

于 2009-02-04T00:30:03.950 回答
1

“输入的JPEG文件是未压缩的”到底是什么意思?Jpegs都是压缩的。

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

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

于 2009-02-04T09:20:33.427 回答