常用图片解码C语言实现

常用

图片解码

// jpage 解码库   libjpeg_turbo
#include "jpeglib.h"
/*
* 功能:解码jpeg图像到指定格式
* 参数:
*       injpeg     输入图像数据指针  可选
*       inLen      对应数据长度      可选
*       infile     输入图像文件指针
*       out        输出解码后的数据
*       outFormat  输出图形格式
*       imgWidth   获取到的 图像宽度
*       imgHeight  获取到的 图像高度
*/
int JPGdecode(char* injpeg, int inLen, FILE * infile, char* out, int outFormat, int *imgWidth, int *imgHeight)
{
	int ret = 0;
	int rowStride = 0;
	int ySize = 0;
	int uvSize = 0;
	char* yPtr = NULL;
	char* uPtr = NULL;
	char* vPtr = NULL;
	char* uvPtr = NULL;
	char *RowBuffer = NULL;

	struct jpeg_decompress_struct dinfo;// 此结构包含JPEG解压缩参数和指针 工作空间(根据JPEG库的需要分配)
	struct jpeg_error_mgr jerr;         // 我们使用我们的专用扩展名JPEG错误处理程序
	struct jpeg_source_mgr s_mgr(unsigned char *injpeg, int inLen);
	dinfo.err = jpeg_std_error(&jerr);          // 我们设置正常的JPEG错误例程
	jpeg_create_decompress(&dinfo);             // 1.初始化JPEG解压缩对象
	dinfo.src = &s_mgr;                         // 2.指定数据源(例如文件)
	//jpeg_stdio_src(&dinfo, infile);           // 输入jpeg图像文件指针模式

	int status = jpeg_read_header(&dinfo, TRUE);// 3.用jpeg_read_header()读取文件参数
	if (status != JPEG_HEADER_OK)
	{
		printf("jpeg header corrupted");
		jpeg_destroy_decompress(&dinfo);
		return ret;
	}
	dinfo.out_color_space = JCS_YCbCr;          // 4. 设置解压缩参数   不设置默认为 rgb格式

	//dinfo.raw_data_out = true;
	// 放大缩小参数
    // dinfo.scale_num=4;   // 分子
	// dinfo.scale_denom=5; // 分母
	// 通过scale_num / scale_denom分数缩放图像。
	// 默认值是1 / 1,或不缩放。目前,唯一支持的缩放比率是M / 8,所有M从1到16,或其任何缩小比例(例如1 / 2,3 / 4等)

	status = jpeg_start_decompress(&dinfo);     // 5. 开始解码
	if (!status)
	{
		printf("jpeg_start_decompress failed");
		return ret;
	}
	*imgWidth  = dinfo.output_width;
	*imgHeight = dinfo.output_height;

	rowStride = dinfo.output_width * dinfo.output_components;//一行的数据长度
	RowBuffer = (char*)malloc(rowStride*sizeof(JSAMPLE));    // 行数据空间

	ySize = dinfo.output_width * dinfo.output_height;        // 一个通道数据量

	ret = ySize * 3 / 2;

	if (outFormat == 0) // HIK_PIXEL_FORMAT_NV21
	{
		yPtr = out;
		uvPtr = out + ySize;
		// 循环调用jpeg_read_scanlines来一行一行地获得解压的数据
		while (dinfo.output_scanline < dinfo.output_height)
		{
			(void)jpeg_read_scanlines(&dinfo, (JSAMPARRAY)&RowBuffer, 1);
			if (dinfo.output_scanline % 2 == 0)
			{
				YuvToNV21Line(RowBuffer, yPtr, uvPtr, dinfo.output_width, TRUE);
				uvPtr += dinfo.output_width;
			}
			else
			{
				YuvToNV21Line(RowBuffer, yPtr, uvPtr, dinfo.output_width, TRUE);
			}
			yPtr += dinfo.output_width;
		}

	}
	else if (outFormat == 1) // HIK_PIXEL_FORMAT_NV12
	{
		yPtr = out;
		uvPtr = out + ySize;
		while (dinfo.output_scanline < dinfo.output_height)
		{
			(void)jpeg_read_scanlines(&dinfo, (JSAMPARRAY)&RowBuffer, 1);
			if (dinfo.output_scanline % 2 == 0)
			{
				YuvToNV12Line(RowBuffer, yPtr, uvPtr, dinfo.output_width, TRUE);
				uvPtr += dinfo.output_width;
			}
			else
			{
				YuvToNV12Line(RowBuffer, yPtr, uvPtr, dinfo.output_width, TRUE);
			}
			yPtr += dinfo.output_width;
		}

	}
	else if (outFormat == 2)// HIK_PIXEL_FORMAT_YV12
	{
		yPtr = out;
		uPtr = out + ySize;
		vPtr = uPtr + (ySize / 4);
		while (dinfo.output_scanline < dinfo.output_height)
		{
			(void)jpeg_read_scanlines(&dinfo, (JSAMPARRAY)&RowBuffer, 1);
			if (dinfo.output_scanline % 2 == 0)
			{
				YuvToYV12Line(RowBuffer, yPtr, uPtr, vPtr, dinfo.output_width, TRUE);
				vPtr += (dinfo.output_width / 2);
				uPtr += (dinfo.output_width / 2);
			}
			else
			{
				YuvToYV12Line(RowBuffer, yPtr, uPtr, vPtr, dinfo.output_width, TRUE);
			}
			yPtr += dinfo.output_width;
		}
	}
	else
	{
		printf("unsupport format(%d)", outFormat);
	}

	jpeg_finish_decompress(&dinfo); // 7. 完成解压缩
	jpeg_destroy_decompress(&dinfo);// 8. 释放JPEG解压缩对象
	if (NULL != RowBuffer)
	{
		free(RowBuffer);
	}

	return ret;
}


opencv

/***************************************************************************************************
* 功  能: 读取图像数据转换成 bbbgggrrr格式后保存
* 参  数: img_path               - I   图像路径
*         dst_w                  - I   目标图像宽度
*         dst_h                  - I   目标图像高度
*         save_file_path         - I   目标图像保存路径
* 返回值: 状态码
***************************************************************************************************/
int read_image_data_to_rrggbb(char  *img_path,
	                          int    dst_w,
	                          int    dst_h,
	                          char  *save_file_path)
{
	int       i, j, k;

	if (NULL == img_path || (NULL == save_file_path))
	{
		printf("path error \r\n");
		return 0;
	}

	IplImage *src_img = cvLoadImage((LPSTR)(LPCTSTR)img_path); // opencv载入图像
	//int       src_w = src_img->width;          // 原图像长宽
	//int       src_h = src_img->height;

	if (NULL == src_img)
	{
		printf("read img error,path:%s \r\n", img_path);
		return -1;
	}


	unsigned char *dst_data = (unsigned char *)malloc(dst_w * dst_h * 3);// 3通道bgr图像 u8数据类型

	IplImage *rsz_img = cvCreateImage(cvSize(dst_w, dst_h), src_img->depth, src_img->nChannels);
	char     *rsz_data = rsz_img->imageData;
	cvResize(src_img, rsz_img);    // 原图形变形到 目标尺寸

	for (j = 0; j < dst_h; j++)    // 每行
	{
		for (i = 0; i < dst_w; i++)// 每列
		{
			for (k = 0; k < 3; k++) // 3通道
			{
				int src_idx = j * dst_w * 3 + i * 3 + k;        // 原图形数据   rgbrgbrgg排列
				int dst_idx = dst_w * dst_h * k + j * dst_w + i;// 目标图像数据 bbbgggrrr排列

				//dst_data[dst_idx] = (float)((unsigned char)rsz_data[src_idx]/* - 128*/)/* * 0.0078125*/; // 浮点类型数据 转换成0~1之间的数据
				dst_data[dst_idx] = (unsigned char)rsz_data[src_idx];
			}
		}
	}
	cvReleaseImage(&src_img);
	cvReleaseImage(&rsz_img);

	FILE *file_out = fopen(save_file_path, "wb"); // 输出模型 可写  二进制格式	

	if (file_out == NULL)
	{
		printf("open file error :%s\n", save_file_path);
		return 0;
	}
	fwrite(dst_data, 1, (dst_w * dst_h * 3), file_out);//保存图像数据
	fclose(file_out);// 关闭文件 

	free(dst_data);

	return 1;
}

/***************************************************************************************************
* 功  能: 读取图像数据转换成 bbbgggrrr格式后保存   填充空白到指定尺寸
* 参  数: img_path               - I   图像路径
*         dst_w                  - I   目标图像宽度
*         dst_h                  - I   目标图像高度
*         save_file_path         - I   目标图像保存路径
* 返回值: 状态码
***************************************************************************************************/
int read_image_data_to_rrggbb_padding(char  *img_path,
	int    dst_w,
	int    dst_h,
	char  *save_file_path)
{
	int       i, j, k;

	if (NULL == img_path || (NULL == save_file_path))
	{
		printf("path error \r\n");
		return 0;
	}

	IplImage *src_img = cvLoadImage((LPSTR)(LPCTSTR)img_path); // opencv载入图像

	if (NULL == src_img)
	{
		printf("read img error,path:%s \r\n", img_path);
		return -1;
	}

	int       src_w = src_img->width;          // 原图像长宽
	int       src_h = src_img->height;
	char     *src_data = src_img->imageData;
	unsigned char *dst_data = (unsigned char *)malloc(dst_w * dst_h * 3);// 3通道bgr图像 u8数据类型

	//IplImage *rsz_img = cvCreateImage(cvSize(dst_w, dst_h), src_img->depth, src_img->nChannels);
	//char     *rsz_data = rsz_img->imageData;
	//cvResize(src_img, rsz_img);    // 原图形变形到 目标尺寸

	for (j = 0; j < dst_h; j++)    // 每行
	{
		if (j < src_h)
		{
			for (i = 0; i < dst_w; i++)// 每列
			{
				if (i < src_w)
				{
					for (k = 0; k < 3; k++) // 3通道
					{
						//int src_idx = j * dst_w * 3 + i * 3 + k;        // 原图形数据   rgbrgbrgg排列
						//int dst_idx = dst_w * dst_h * k + j * dst_w + i;// 目标图像数据 bbbgggrrr排列
						//dst_data[dst_idx] = (float)((unsigned char)rsz_data[src_idx]/* - 128*/)/* * 0.0078125*/; // 浮点类型数据 转换成0~1之间的数据
						//dst_data[dst_idx] = (unsigned char)rsz_data[src_idx];

						int src_idx = j * src_w * 3 + i * 3 + k;        // 原图形数据   rgbrgbrgg排列
						int dst_idx = dst_w * dst_h * k + j * dst_w + i;// 目标图像数据 bbbgggrrr排列
						dst_data[dst_idx] = (unsigned char)src_data[src_idx];
					}
				}
				else
				{

				}
			}

		}
		else
		{

		}
	}
	cvReleaseImage(&src_img);
	//cvReleaseImage(&rsz_img);

	FILE *file_out = fopen(save_file_path, "wb"); // 输出模型 可写  二进制格式	

	if (file_out == NULL)
	{
		printf("open file error :%s\n", save_file_path);
		return 0;
	}
	fwrite(dst_data, 1, (dst_w * dst_h * 3), file_out);//保存图像数据
	fclose(file_out);// 关闭文件 

	free(dst_data);

	return 1;
}



/* 读取图像img  缩放到固定尺寸 保存成 NV21图 y平铺 uv交织*/
int read_image_data_to_NV21(char  *img_path,
	int    dst_w,
	int    dst_h,
	char  *save_file_path)
{
	int       i, j, k;

	if (NULL == img_path || (NULL == save_file_path))
	{
		printf("path error \r\n");
		return 0;
	}

	IplImage *src_img = cvLoadImage((LPSTR)(LPCTSTR)img_path); // opencv载入图像
	//int       src_w = src_img->width;          // 原图像长宽
	//int       src_h = src_img->height;

	if (NULL == src_img)
	{
		printf("read img error,path:%s \r\n", img_path);
		return -1;
	}

	// 1. 缩放到 bgr图
	unsigned char *dst_data = (unsigned char *)malloc(dst_w * dst_h * 3);// 3通道bgr图像 u8数据类型  
	unsigned char *dst_nv21_data = (unsigned char *)malloc(dst_w * dst_h * 3); // y + vu

	IplImage *rsz_img = cvCreateImage(cvSize(dst_w, dst_h), src_img->depth, src_img->nChannels);
	char     *rsz_data = rsz_img->imageData;
	cvResize(src_img, rsz_img);    // 原图形变形到 目标尺寸

	for (j = 0; j < dst_h; j++)    // 每行
	{
		for (i = 0; i < dst_w; i++)// 每列
		{
			for (k = 0; k < 3; k++) // 3通道
			{
				int src_idx = j * dst_w * 3 + i * 3 + k;        // 原图形数据   rgbrgbrgg排列
				int dst_idx = dst_w * dst_h * k + j * dst_w + i;// 目标图像数据 bbbgggrrr排列

				//dst_data[dst_idx] = (float)((unsigned char)rsz_data[src_idx]/* - 128*/)/* * 0.0078125*/; // 浮点类型数据 转换成0~1之间的数据
				dst_data[dst_idx] = (unsigned char)rsz_data[src_idx];
			}
		}
	}
	cvReleaseImage(&src_img);
	cvReleaseImage(&rsz_img);

	// 2. bgr 平铺转 nv21
	int channel_step = dst_h*dst_w;
	int Yindex = 0, UVindex = 0;
	unsigned char *dst_nv21_data_vu_p = dst_nv21_data + channel_step;
	for (int i = 0; i < dst_h; i++)
	{
		for (int j = 0; j < dst_w; j++)
		{
			int channel_in_step = i*dst_h + j;
			unsigned char *src_b_p = dst_data + channel_in_step;
			unsigned char *src_g_p = dst_data + channel_in_step + channel_step;
			unsigned char *src_r_p = dst_data + channel_in_step + channel_step * 2;

			//计算Y的值
			int Y = (77 * (*src_r_p) + 150 * (*src_g_p) + 29 * (*src_b_p)) >> 8;
			dst_nv21_data[Yindex++] = (Y < 0) ? 0 : ((Y > 255) ? 255 : Y);
			//计算U、V的值,进行2x2的采样
			if (i % 2 == 0 && (j) % 2 == 0)
			{
				int U = ((-44 * (*src_r_p) - 87 * (*src_g_p) + 131 * (*src_b_p)) >> 8) + 128;
				int V = ((131 * (*src_r_p) - 110 * (*src_g_p) - 21 * (*src_b_p)) >> 8) + 128;

				dst_nv21_data_vu_p[UVindex++] = (V < 0) ? 0 : ((V > 255) ? 255 : V);
				dst_nv21_data_vu_p[UVindex++] = (U < 0) ? 0 : ((U > 255) ? 255 : U);
			}
		}
	}


	FILE *file_out = fopen(save_file_path, "wb"); // 输出模型 可写  二进制格式	

	if (file_out == NULL)
	{
		printf("open file error :%s\n", save_file_path);
		return 0;
	}
	fwrite(dst_nv21_data, 1, (dst_w * dst_h * 3 / 2), file_out);//保存图像数据
	fclose(file_out);// 关闭文件 

	free(dst_data);
	free(dst_nv21_data);

	return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值