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.jpg
2.jpg
上一篇下一篇

猜你喜欢

热点阅读