美文网首页
c语言实现图像二值化

c语言实现图像二值化

作者: 一路向后 | 来源:发表于2021-06-20 23:26 被阅读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

    相关文章

      网友评论

          本文标题:c语言实现图像二值化

          本文链接:https://www.haomeiwen.com/subject/nyjeyltx.html