2024-04-16 使用C语言把FMT_YUV400SP (gray8)/* YYYY... */格式的数据转换为 JPEG 文件

一、简单介绍一下FMT_YUV400SP(gray8)图像数据格式

       在 FMT_YUV400SP 中,只有一个平面,即亮度平面(Y)。这意味着每个像素只有一个亮度值灰度图像或单通道图像,例如黑白摄像头捕获的图像或某些图像处理操作的中间结果。总之,FMT_YUV400SP 是一种仅包含亮度分量的图像格式,没有色度分量,通常用于表示灰度图像数据。

二、FMT_YUV400SP (gray8)/* YYYY...    */格式的数据转换为 JPEG 文件

       要将 FMT_YUV400SP 格式的数据转换为 JPEG 文件,您可以使用一些库来处理图像编码和文件写入。在 C 语言中,您可以使用像 libjpeg 这样的库来实现这个任务。

以下是一个简单的示例,演示了如何使用 libjpeg 库将 FMT_YUV400SP 格式的数据转换为 JPEG 文件

三、测试C语言

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

// 将 FMT_YUV400SP 数据编码为 JPEG 文件
void yuv400sp_to_jpeg(unsigned char* yuv400sp_data, int width, int height, const char* output_filename) {
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE *outfile;
    JSAMPROW row_pointer[1];
    int row_stride;

    // 打开输出 JPEG 文件
    if ((outfile = fopen(output_filename, "wb")) == NULL) {
        fprintf(stderr, "Cannot open output file %s\n", output_filename);
        return;
    }

    // 初始化 JPEG 压缩结构体
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

    // 设置图像参数
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 1; // 1 个亮度分量
    cinfo.in_color_space = JCS_GRAYSCALE; // 灰度图像

    // 设置 JPEG 压缩参数
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 90, TRUE);

    // 开始压缩
    jpeg_start_compress(&cinfo, TRUE);

    // 逐行压缩图像数据
    row_stride = width;
    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = &yuv400sp_data[cinfo.next_scanline * row_stride];
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    // 完成压缩
    jpeg_finish_compress(&cinfo);

    // 释放资源
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);
}


int main() {
    // 假设您有 FMT_YUV400SP 数据和图像宽度和高度
    int width = 1024; // 图像宽度
    int height = 1280; // 图像高度
    unsigned char* yuv400sp_data = (unsigned char *)malloc(width * height);
    FILE *input_file = fopen("cowboy_girl_1024X1280_y8.yuv", "rb");
    if (!input_file) {
        fprintf(stderr, "Error opening input file.\n");
        return 1;
    }

    fread(yuv400sp_data, 1, width*height, input_file);

    // 将 FMT_YUV400SP 数据转换为 JPEG 文件
    yuv400sp_to_jpeg(yuv400sp_data, width, height, "output.jpg");

    return 0;
}

四、测试效果

五、在另外一个地方看到的函数,类似。

void demo_compress_jpeg_y8(uint8_t *jpegbuff, int *len, unsigned char *buffsrc, int width, int height, int quality)
{

    struct jpeg_error_mgr jerr;

    JSAMPLE * imageBuffer = (JSAMPLE *)buffsrc;
    struct jpeg_compress_struct cinfo = {
            .client_data = NULL, .err = jpeg_std_error(&jerr)
    };

    jpeg_create_compress(&cinfo);

    struct jpeg_destination_mgr dm = {
        .init_destination = init_buffer, 
	.empty_output_buffer = empty_buffer,
        .term_destination = term_buffer, 
	.next_output_byte = jpegbuff,
        .free_in_buffer = *len
    };
    cinfo.dest = &dm;

    cinfo.image_width = (JDIMENSION) width;
    cinfo.image_height = (JDIMENSION) height;

    // 这里是一个通道的灰度图buffer, 如果使RGB图,可以设置JCS_RGB,input_components = 3;
    cinfo.in_color_space = JCS_GRAYSCALE;
    cinfo.jpeg_color_space = JCS_GRAYSCALE;
    cinfo.input_components = 1;

    jpeg_set_defaults(&cinfo);

    jpeg_set_quality(&cinfo, quality, TRUE); // TRUE = limit to baseline-JPEG values

    cinfo.MCUs_per_row = (JDIMENSION) width;
    cinfo.MCU_rows_in_scan = (JDIMENSION) height;

    jpeg_start_compress(&cinfo, TRUE);

    int row_stride; // physical row width in image buffer
    row_stride = width * cinfo.input_components; // JSAMPLEs per row in imageBuffer

    JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = &imageBuffer[cinfo.next_scanline * row_stride];
        (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);

    jpeg_destroy_compress(&cinfo);

    int size = (int) (cinfo.dest->next_output_byte - jpegbuff);
    *len = size;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值