使用C语言实现简单的PNG图像读取

这篇具有很好参考价值的文章主要介绍了使用C语言实现简单的PNG图像读取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

首先,关于png图像的结构:PNG文件的结构、PNG格式的数据结构。这两篇文章说的比较细。我简单地说一下我使用到的地方:

注:①引于PNG格式的数据结构。②引于PNG文件的结构

“png文件的前8个字节为固定的文件头信息,表明为png文件,其后便为IHDR。
IHDR的前1-4字节表示IHDR的长度(00 00 00 0D),可知长度为13。5-8字节(49 48 44 52)为数据块类型码,表明数据块为IHDR。9-16字节存储了图像的宽高信息(00 00 20 00 00 00 20 00),可知图片的宽高为512x512。其后的5个字节分别表示了图像的色深、颜色类型、滤波器方法、隔行扫描方法,最后四个字节为CRC循环冗余检测。” ①

IHDR由13字节组成:

名称 字节数 说明
Width 4字节 图像宽度(像素)
Height 4字节 图像高度(像素)
Bit depth 1字节 图像深度:表示每个采样点占用的bit数
索引(indexed)彩色图像:1,2,4或8;
灰度图像:1,2,4,8或16;
真彩色图像:8或16
Colour type 1字节 颜色类型:
0:灰度图像, 深度为1,2,4,8或16 bit;
2:真彩色(truecolor)图像,深度为8或16 bit;
3:索引彩色图像,深度为1,2,4或8 bit;
4:带α通道数据的灰度图像,深度为8或16 bit;
6:带α通道数据的真彩色(truecolor with alpha)图像,深度为8或16 bit
Compression method 1字节 压缩方法:
0:LZ77派生算法(目前仅定义了0)
其他值:无效;为未来扩展的压缩方法预留
Filter method 1字节 滤波器方法:
0(目前仅定义了0)
其他值:无效
Interlace method 1字节 隔行扫描方法:
0:非隔行扫描;
1: Adam7隔行扫描方法

”②

作为初学者,我个人的想法是创建一个图片结构体,将整张图片以byte[]形式存储,然后设置偏移值跳过不需要的信息,然后使用联合将需要转换的信息转换为相应的数据类型并储存即可。

联合部分:使用联合将4个byte与1个int共用一片存储空间,反向读取整个图片的byte[]数组,对于4字节长的width与height信息,正向存储于联合的byte[]数组,达到byte[]转int的效果。

代码


/*
 * 处理PNG图片的c文件
 * */
#include <stdio.h>
#include <windows.h>
//定义PNG图片体
typedef struct pictureTypedPNG{
    //存储图片路径
    char* path;
    //图像宽度、图像高度
    int width, height;
    //图片大小
    long long pictureSize;
    //图像深度、颜色类型、压缩方法、滤波器方法、隔行扫描方法
    byte depth, colorType, compressionMethod, filterMethod, interlaceMethod;
    //图像本体存储在这里
    byte* body;
}png;

//定义byte转int的联合体
typedef union byteToInt{
    __attribute__((unused)) byte b[4];//只做转换用,不直接调用
    int i;
}byteToInt;

//图片读取
png* getPNG(char* path){
    png* p = (png*)malloc(sizeof(png));
    FILE *fp = fopen(path, "rb");//打开文件。
    if (fp == NULL) // 打开文件失败
        return p;
    //存储路径
    p->path = (char*) malloc((sizeof(char) * strlen(path)));
    strcpy(p->path, path);
    //获取文件大小
    fseek(fp, 0, SEEK_END);//定位文件指针到文件尾。
    p->pictureSize = ftell(fp);//获取文件指针偏移量,即文件大小。
    fseek(fp, 0, SEEK_SET);//定位文件指针到文件头。
    //获取图片体
    p->body = (byte*) malloc(sizeof(byte) * p->pictureSize);//分配存储图片文件的内存
    fread(p->body, 1, p->pictureSize, fp);//读取图片体
    //多byte转int
    byteToInt bti;
    //获取图片部分信息。设置偏移值滤除文件头、IHDR标识信息
    int offset = 8 + 8;
    //获取图像宽度
    for(int i = 3, j = 0; i >= 0; i--, j++){
        bti.b[i] = p->body[j + offset];
    }
    p->width = bti.i;
    //获取图像高度
    for(int i = 3, j = 0; i >= 0; i--, j++){
        bti.b[i] = p->body[j + offset + 4];
    }
    p->height = bti.i;
    //获取图像深度
    p->depth = p->body[8 + offset];
    //获取颜色类型
    p->colorType = p->body[9 + offset];
    //获取压缩方法
    p->compressionMethod = p->body[10 + offset];
    //获取滤波器方法
    p->filterMethod = p->body[11 + offset];
    //获取隔行扫描方法
    p->interlaceMethod = p->body[12 + offset];
    fclose(fp);//关闭文件。
    return p;
}
void printPNG(const png* p){
    const char* colorType = NULL;
    const char* compressionMethod = NULL;
    const char* filterMethod = NULL;
    const char* interlaceMethod = NULL;
    switch(p->colorType){
        case 0: colorType = "灰度图像";break;
        case 2: colorType = "真彩色图像";break;
        case 3: colorType = "索引彩色图像";break;
        case 4: colorType = "带α通道的灰度图像";break;
        case 6: colorType = "带α通道的真彩色图像";break;
    }
    if(!p->compressionMethod){
        compressionMethod = "LZ77派生算法";
    }
    if(!p->filterMethod){
        filterMethod = "0";
    }
    if(p->interlaceMethod){
        interlaceMethod = "Adam7隔行扫描方法";
    }else{
        interlaceMethod = "非隔行扫描";
    }
    printf("图像路径:%s\n"
           "图像大小:%lld\n"
           "图像宽度(像素):%d\n"
           "图像高度(像素):%d\n"
           "图像深度:%hhu\n"
           "颜色类型:%s\n"
           "压缩方法:%s\n"
           "滤波器方法:%s\n"
           "隔行扫描方法:%s\n", p->path, p->pictureSize, p->width, p->height,
           p->depth, colorType, compressionMethod, filterMethod, interlaceMethod);
}
int main() {
    printf("请输入图片路径: \n");
    char* path = (char*)malloc(sizeof(char) * 100);
    fgets(path, 100, stdin);
    int len = (int)strlen(path);
    *(path + len - 1) = '\0';
    png* picture = getPNG(path);
    printPNG(picture);
    return 0;
}

实现效果 

使用C语言实现简单的PNG图像读取文章来源地址https://www.toymoban.com/news/detail-461872.html

到了这里,关于使用C语言实现简单的PNG图像读取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • PDF处理控件Aspose.PDF功能演示:使用Java将Base64字符串转换为PDF/JPG/PNG图像

    PDF处理控件Aspose.PDF功能演示:使用Java将Base64字符串转换为PDF/JPG/PNG图像

    Aspose.PDF  是一款高级PDF处理API,可以在跨平台应用程序中轻松生成,修改,转换,呈现,保护和打印文档。无需使用Adobe Acrobat。此外,API提供压缩选项,表创建和处理,图形和图像功能,广泛的超链接功能,图章和水印任务,扩展的安全控件和自定义字体处理。 Aspose API支持

    2024年02月04日
    浏览(15)
  • chatgpt赋能Python-python_读取png

    Python是一种高级编程语言,尤为擅长处理数据科学和机器学习方面的应用。PNG(Portable Network Graphics)是一种流行的图像格式,它使用无损压缩技术来存储图像数据。在本文中,我们将介绍如何使用Python读取PNG图像。 PNG是一种图像格式,它旨在替代GIF(Graphics Interchange Format)

    2024年02月06日
    浏览(7)
  • perl语言读取文件夹中所有的bmp图像

    工作中会经常遇到测试所有图像的需求,使用perl语言进行bmp图像读入,示例代码如下: 请确保将 /path/to/folder 替换为实际的文件夹路径,其中包含你要读取的BMP图像文件。代码遍历文件夹中的每个文件,使用正则表达式过滤出BMP图像文件,然后可以在循环中对每个图像文件执

    2024年02月16日
    浏览(6)
  • Python读取红外图像 - 实现红外图像的读取和处理

    Python读取红外图像 - 实现红外图像的读取和处理 在许多工业、安防等领域中,红外图像无疑是一种不可或缺的重要资源。因此,能够快速、准确地读取和处理红外图像,对于工程师和科学家来说非常必要。 Python作为一种强大的编程语言,提供了丰富的图像处理库,允许我们

    2024年02月11日
    浏览(3)
  • C++&Python&C# 三语言OpenCV从零开发(3):图像读取和显示

    C++&Python&C# 三语言OpenCV从零开发(3):图像读取和显示

    C++PythonCsharp in OpenCV 专栏 【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程(附带课程课件资料+课件笔记) OpenCV4 C++ 快速入门视频30讲 - 系列合集 OpenCV4 C++ 课程笔记 在上一章纠结过教程的选择之后,还是觉得老老实实从零开始学OpenCV,从OpenCV C++视频教程开始。 这

    2024年01月21日
    浏览(18)
  • 【设计模式】使用 go 语言实现简单工厂模式

    最近在看《大话设计模式》,这本书通过对话形式讲解设计模式的使用场景,有兴趣的可以去看一下。 第一篇讲的是 简单工厂模式 ,要求输入两个数和运算符号,得到运行结果。 这个需求不难,难就难在类要怎么设计,才能达到可复用、维护性强、可拓展和灵活性高。 运

    2024年02月05日
    浏览(13)
  • 使用C语言实现简单的通用的链表

    使用C语言实现简单的通用的链表

    在数据结构中,我们已经学习到了简单的静态链表以及单链表和双链表,它们各有优缺点,但是有个共同的问题是他们呢无法存储不同的数据。下面提供了一种方法,可以将不同节点的数据链接起来。 下面的代码都是基础的C语言代码,涉及到的知识点基本覆盖到C语言学习的

    2024年02月08日
    浏览(6)
  • 【数据压缩】第二次作业——PNG图像格式分析

    【数据压缩】第二次作业——PNG图像格式分析

    PNG格式是一种采用无损压缩算法的位图格式,支持索引、灰度、RGB三种颜色方案以及alpha通道等特性。 PNG能够支持256色调色板技术,产生文件的体积小,最高支持24位真彩色图像以及8位灰度图像,支持存在附加文本信息,以保留图像名称、作者、著作权、创作时间、注释等,

    2023年04月08日
    浏览(5)
  • UE4将读取的PNG图片数据转换为UTexture2D并显示

    UE4将读取的PNG图片数据转换为UTexture2D并显示

    从硬盘中读取压缩过的图片文件到二进制数组,获取已压缩的数据; 将已压缩的数据借助ImageWrapper中的GetRaw函数转换为原始RGB数据; 填充原始RGB数据到UTexture2D中。 处理图片类型需要使用UE提供的ImageWrapper模块,首先在project.Build.cs中加入ImageWrapper模块。 ImageWrapper是所有图片

    2024年02月15日
    浏览(6)
  • SpringMVC概述与简单使用

    SpringMVC概述与简单使用

    SpringMVC也叫做Spring web mvc,是 Spring 框架的一部分,是在 Spring3.0 后发布的。 3.1.1 新建一个webapp项目 3.1.2 pom.xml文件书写 3.1.3 注册中央调度器 3.1.4 创建处理器 3.1.5 声明组件扫描器 3.1.6 在webapp目录下定义目标界面 3.1.7 1.3.8 修改视图解析器的注册 (1)浏览器提交请求到中央调度

    2024年02月10日
    浏览(5)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包