一、简单介绍一下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;
}