c语言实现图像二值化
2021-06-20 本文已影响0人
一路向后
1.源码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <jpeglib.h>
typedef struct ImagePicData ImagePicData;
struct ImagePicData
{
unsigned char fname[256];
FILE *fp;
int width;
int height;
int bitdep;
int flag;
int type;
unsigned char *rgba;
};
int loadJPG(ImagePicData *ImageData)
{
JSAMPARRAY JpegBuffer;
struct jpeg_decompress_struct JpegInfo;
struct jpeg_error_mgr JpegError;
int RowStride;
int pos;
int i;
ImageData->fp = NULL;
if((ImageData->fp=fopen(ImageData->fname, "rb")) == NULL)
{
printf("can't open %s\n", ImageData->fname);
return -1;
}
//初始化并申请解码器
JpegInfo.err = jpeg_std_error(&JpegError);
jpeg_create_decompress(&JpegInfo);
//指定图片文件信息
jpeg_stdio_src(&JpegInfo, ImageData->fp);
//读取头部信息
jpeg_read_header(&JpegInfo, TRUE);
//开始解码
jpeg_start_decompress(&JpegInfo);
ImageData->width = JpegInfo.output_width;
ImageData->height = JpegInfo.output_height;
RowStride = JpegInfo.output_width * JpegInfo.output_components;
ImageData->bitdep = 8;
ImageData->flag = 1;
ImageData->type = 1;
pos = 0;
JpegBuffer = (*JpegInfo.mem->alloc_sarray)((j_common_ptr)&JpegInfo, JPOOL_IMAGE, RowStride, 1);
//一行一行读取
while(JpegInfo.output_scanline < ImageData->height)
{
jpeg_read_scanlines(&JpegInfo, JpegBuffer, 1);
for(i=0; i<ImageData->width; i++)
{
ImageData->rgba[4*pos+0] = JpegBuffer[0][3*i+0];
ImageData->rgba[4*pos+1] = JpegBuffer[0][3*i+1];
ImageData->rgba[4*pos+2] = JpegBuffer[0][3*i+2];
ImageData->rgba[4*pos+3] = 255;
pos++;
}
}
//读取结束
jpeg_finish_decompress(&JpegInfo);
//释放编码器对象
jpeg_destroy_decompress(&JpegInfo);
fclose(ImageData->fp);
ImageData->fp = NULL;
return 0;
}
int saveJPG(ImagePicData *ImageData)
{
JSAMPARRAY JpegBuffer;
struct jpeg_compress_struct JpegInfo;
struct jpeg_error_mgr JpegError;
int RowStride;
int pos;
int i;
ImageData->fp = NULL;
if((ImageData->fp=fopen(ImageData->fname, "wb")) == NULL)
{
printf("fopen %s error!\n", ImageData->fname);
return -1;
}
//初始化申请编码器
JpegInfo.err = jpeg_std_error(&JpegError);
jpeg_create_compress(&JpegInfo);
//指定图片文件信息
jpeg_stdio_dest(&JpegInfo, ImageData->fp);
//设置图片参数
JpegInfo.image_width = ImageData->width;
JpegInfo.image_height = ImageData->height;
JpegInfo.input_components = 3;
JpegInfo.in_color_space = JCS_RGB;
pos = 0;
//设置文件头信息
jpeg_set_defaults(&JpegInfo);
//jpeg_set_quality(&JpegInfo, 100, TRUE);
RowStride = ImageData->width * 3;
JpegBuffer = (*JpegInfo.mem->alloc_sarray)((j_common_ptr)&JpegInfo, JPOOL_IMAGE, RowStride, 1);
//开始编码
jpeg_start_compress(&JpegInfo, TRUE);
//一行一行写
while(JpegInfo.next_scanline < ImageData->height)
{
for(i=0; i<ImageData->width; i++)
{
JpegBuffer[0][3*i+0] = ImageData->rgba[4*pos+0];
JpegBuffer[0][3*i+1] = ImageData->rgba[4*pos+1];
JpegBuffer[0][3*i+2] = ImageData->rgba[4*pos+2];
pos++;
}
jpeg_write_scanlines(&JpegInfo, JpegBuffer, 1);
}
//写入结束
jpeg_finish_compress(&JpegInfo);
//释放编码器对象
jpeg_destroy_compress(&JpegInfo);
fclose(ImageData->fp);
ImageData->fp = NULL;
return 0;
}
int binaryzJPG(ImagePicData *ImageData, int alpha)
{
int pos = 0;
short x;
int i, j;
for(i=0; i<ImageData->height; i++)
{
for(j=0; j<ImageData->width; j++)
{
x = 0.299 * (double)ImageData->rgba[4*pos+0] + 0.587 * (double)ImageData->rgba[4*pos+1] + 0.114 * (double)ImageData->rgba[4*pos+2];
x = x > alpha ? 255 : 0;
ImageData->rgba[4*pos+0] = x;
ImageData->rgba[4*pos+1] = x;
ImageData->rgba[4*pos+2] = x;
pos++;
}
}
return 0;
}
int main(int argc, char **argv)
{
unsigned char rgba[4*1024*1024];
ImagePicData ImageData;
int ret;
if(argc < 2)
{
return -1;
}
ImageData.rgba = rgba;
strcpy(ImageData.fname, argv[1]);
ret = loadJPG(&ImageData);
if(ret != 0)
{
return -1;
}
binaryzJPG(&ImageData, 128);
strcpy(ImageData.fname, argv[2]);
saveJPG(&ImageData);
return 0;
}
2.编译及运行
$ gcc -o example example.c -std=c99 -I$HOME/local/include -ljpeg -L$HOME/local/lib
$ ./example 1.jpg 2.jpg
3.结果展示
1.jpg2.jpg