【问题标题】:Read in JPEG, resize it and save it to disk读取 JPEG,调整大小并将其保存到磁盘
【发布时间】:2025-11-25 01:10:01
【问题描述】:

我想要什么:

将现有 jpeg 调整为新的较小的 jpeg。

示例:before_3000x2000.jpeg →→→ after_1024x768.jpeg

我想我需要像这样的伪函数:

foo( before_file_path, after_file_path, new_width, new_height )

利用

decompress_jpeg( before_file_path )

resize(decompressed_data, new_width, new_height)

compress_jpeg(resized_data)

save_jpeg(compressed_data, after_file_path)

如果我误解了什么,请纠正我的方法。

我的假设:

  • 由于分辨率会有所不同,首先您必须解压缩现有的 jpeg,以便正确处理像素数据。
  • 其次,使用一些函数 foo() 将像素数据调整为更小的缓冲区。
  • 第三,压缩所述缓冲区并将其保存到磁盘。

我尝试过(但失败了):

对于初学者,我试着玩弄

write_JPEG_file(char * 文件名,int 质量)

jpeglib-9bexample.c中提供的函数。我只想用我指定的任何分辨率用单色写出一张测试图片。但是我遇到了一个问题。我认为我正在写出随机内存,但我不知道为什么。 (这是一张图片:img_100x100)注意顶部是如何达到一定程度的白色。这部分会根据我在第一个循环中分配的内容而改变。但经过一定量后,它会变为随机噪声。 为什么?

我改变了什么:

我定义了image_width, image_height, image_buffer
我用fopen_s(...)替换了所有fopen(...)
我在jpeg_set_quality(...) 中将质量硬编码为 100

代码:

#include <iostream>
#include "jpeg-9b\jpeglib.h"
#include "jpeg-9b\jerror.h"

int TEST_WRITE_JPEG(char* file_name)
{
    // DEFINE A PIC HERE
    const int image_width = 100;        /* Number of columns in image */
    const int image_height = 100;   /* Number of rows in image */
    JSAMPLE* image_buffer = new JSAMPLE[image_width * image_height]();  /* Points to large array of R,G,B-order data */
    for (int i = 0; i < image_width*image_height; i++)
    {
        image_buffer[i] = 255;
    }

    /* Step 1: allocate and initialize JPEG compression object */
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE * outfile;
    JSAMPROW row_pointer[1];
    int row_stride;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);

    /* Step 2: specify data destination (eg, a file) */
    if (fopen_s(&outfile, file_name, "wb") != NULL)
    {
        fprintf(stderr, "can't open %s\n", file_name);
        exit(1);
    }
    jpeg_stdio_dest(&cinfo, outfile);

    /* Step 3: set parameters for compression */
    cinfo.image_width = image_width;    /* image width and height, in pixels */
    cinfo.image_height = image_height;
    cinfo.input_components = 3;         /* # of color components per pixel */
    cinfo.in_color_space = JCS_RGB;     /* colorspace of input image */

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 100, TRUE);

    /* Step 4: Start compressor */
    jpeg_start_compress(&cinfo, TRUE);

    /* Step 5: while (scan lines remain to be written) */
    row_stride = image_width * 3;

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

    /* Step 6: Finish compression */
    jpeg_finish_compress(&cinfo);
    /* After finish_compress, we can close the output file. */
    fclose(outfile);

    /* Step 7: release JPEG compression object */
    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_compress(&cinfo);

    return 0;
}

明确问题:

为什么我写出this图片而不是纯白色的?
如果image_buffer 包含超过 128x128 个无符号字符,为什么程序会崩溃?

【问题讨论】:

  • 你不想这样做。您想用较低的 Q 保存它。这种方法会使数据像素化。
  • @EJP 我不想具体做什么?我假设您在谈论调整大小的部分?请详细说明一下好吗?

标签: c++ windows jpeg libjpeg


【解决方案1】:

每个像素使用 3 个字节,因此您必须分配 3 * image_width * image_height 元素,而您只分配 image_width * image_height 元素。分配和初始化足够的元素。

【讨论】:

  • 是的,在我点击提交 3 秒后,我立即看到了这一点。哇这很尴尬。非常感谢你!这解决了一切。没有崩溃,非常适合更大的尺寸。还不能接受你的回答,因为太早了。
最近更新 更多