数据压缩第三次作业-RGB文件的读取

数据压缩第三次作业-RGB文件的读取

读入一个24bitRGB文件(以down.rgb为例,其分辨率为256*256),输出该数据文件中R、G、B三个分量(各8bit表示)的概率分布示意图和熵。

一、思路及代码

结合上个小学期视频处理的练习,在C中打开处理文件的思路主要分为以下几个部分:
1.创建文件-fopen
2.创建内存空间-buffer malloc
3.读取文件-fread
4.处理-measure
5.写文件-fwrite
6.释放内存空间-free malloc
7.关闭文件-fclose
其中第4部分 处理-measure 对于不同的具体任务而不同,在本例子中meas部分包含三基色存储、计算频率、计算香农熵三个小部分

#include <stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>


int main()
{
    errno_t err;
    FILE* photo;
    FILE* pBsat;
    FILE* pGsat;
    FILE* pRsat;
    constexpr auto width = 256;;
    constexpr auto height = 256;;
    //fopen
   err= fopen_s(&photo, "down.rgb", "rb");
    if (err == 0) {
        printf("打开文件成功!\n");
    }
    else {
        printf("打开文件失败!\n");
    }
    err= fopen_s(&pBsat, "B_sat.txt", "w");
    if (err == 0) {
        printf("创建B_sat.txt成功!\n");
    }
    else {
        printf("创建B_sat.txt失败!\n");
    }
    err= fopen_s(&pGsat, "G_sat.txt", "w");

    if (err == 0) {
        printf("创建G_sat.txt成功!\n");
    }
    else {
        printf("创建G_sat.txt失败!\n");
    }

    err= fopen_s(&pRsat, "R_sat.txt", "w");
    if (err == 0) {
        printf("创建R_sat.txt成功!\n");
    }

    else {
        printf("创建R_sat.txt失败!\n");
    }

    //buffer malloc
    unsigned char* buffer = NULL;
    buffer= (unsigned char*)malloc(sizeof(unsigned char) * 3 * width *
height);
    if (NULL != buffer)
    {
        printf("申请内存成功!\n");
    }
    else
    {
        printf("申请内存失败!\n");
    }
 

    //fread

    fread(buffer,sizeof(unsigned char), 3 * width * height, photo);
 
    //measure

    //分成三基色存储

    unsigned char B[width * height] ={ 0 };
    unsigned char G[width * height] ={ 0 };
    unsigned char R[width * height] ={ 0 };
    int pB = 0;
    int pG = 0;
    int pR = 0;

    for (int i = 0; i <3*width*height; i++)
    {
        if (i % 3 == 0)
        {
             B[pB]= *(buffer+i);
             pB++;
        }
        else if(i % 3 == 1)
        {
             G[pG]= *(buffer + i);
             pG++;
        }
        else if (i % 3 == 2)
        {
             R[pR]= *(buffer + i);
             pR++;
        }
    }
    if (pB == width *height && pG == width * height && pR == width * height)
    {
        printf("RGB数据读取成功!\n");
    }
    else
    {
        printf("RGB数据读取失败!\n");
    }

    //计算频率
    int numB[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        for (int j = 0; j < width* height; j++)
        {
             if (i == B[j])
             {
                 numB[i]++;
             }
        }
    }
    double freqB[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        freqB[i]= double(numB[i]) / (width *height);
    }

    int numG[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        for (int j = 0; j < width* height; j++)
        {
             if (i == G[j])
             {
                 numG[i]++;
             }
        }
    }
    double freqG[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        freqG[i]= double(numG[i]) / (width *height);
    }
    int numR[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        for (int j = 0; j < width* height; j++)
        {
             if (i == R[j])
             {
                 numR[i]++;
             }
        }
    }
    double freqR[256] = { 0 };
    for (int i = 0; i < 256;i++)
    {
        freqR[i]= double(numR[i]) / (width *height);
    }

 
    //计算香农熵

    double HB = 0;

    double HG = 0;

    double HR = 0;

    for (int i = 0; i < 256;i++)
    {
        if (freqB[i] != 0)
        {
             HB= HB - freqB[i] * log(freqB[i]) / log(2);
        }

        if (freqG[i] != 0)
        {
             HG= HG - freqG[i] * log(freqG[i]) / log(2);
        }
        if (freqR[i] != 0)
        {
             HR= HR - freqR[i] * log(freqR[i]) / log(2);
        }
    }
    printf("B基色的香农熵是%f\n",HB);
    printf("G基色的香农熵是%f\n", HG);
    printf("R基色的香农熵是%f\n", HR);

    //fwrite
    fprintf(pBsat,"symbol\tfreq\n");
    for (int i = 0; i < 256;i++)
    {
        fprintf(pBsat,"%d\t%f\n",i,freqB[i]);
    }
    fprintf(pGsat,"symbol\tfreq\n");
    for (int i = 0; i < 256;i++)
    {
        fprintf(pGsat,"%d\t%f\n", i,freqG[i]);
    }
    fprintf(pRsat,"symbol\tfreq\n");
    for (int i = 0; i < 256;i++)
    {
        fprintf(pRsat,"%d\t%f\n", i,freqR[i]);
    }
 

    //free malloc
    free(buffer);

 
    //fclose
    fclose(photo);
    fclose(pBsat);
    fclose(pGsat);
    fclose(pRsat);
    printf("文件关闭!\n");

 
    //system pause
    system("pause");

    return 0;
}

在visual studio 2019中运行上述代码,可以得到一下结果:
在这里插入图片描述从图中可以看出,RGB三种基色符号在down.rgb文件中的香农熵依次为7.23、7.18、6.86。

ps:上述代码有几个要注意的点
1.目标文件down.rgb要和源文件cpp放在同一路径中。
2.在vs2019中,使用fopen_s代替fopen,相应的使用方法也不一样
3.计算freq时,因为要做除法,所以要把int型数据转为double型,否则结果会都变为0

二、绘图

使用excel打开生成的txt文件,框选相应的数据,绘制条形图,可以得到以下结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、使用matlab的简单代码

matlab自带的读取文件函数和绘图函数可以非常简介的完成读取文件数据以及绘制精美图像的操作。
例如在C中十分复杂、需要占用大量篇幅的读取文件操作,在matlab中可以仅用三行代码实现将rgb文件的数据存储到矩阵A中,然后进行后续的作图处理

fileID = fopen('down.rgb');
A = fread(fileID);
fclose(fileID);

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值