使用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图像

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

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

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

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

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

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

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

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

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

    2024年01月21日
    浏览(59)
  • 使用C语言实现简单的通用的链表

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

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

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

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

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

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

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

    2024年02月15日
    浏览(39)
  • SQLite简单概述以及使用

          SQLite是一种轻量级的关系型数据库管理系统,它不需要独立的服务器进程,也不需要配置多个参数,就可以直接访问一个文件中的数据库,它以C语言库的形式提供了一个嵌入式的数据库引擎,支持SQL语言标准的大部分功能,但相比于MySQL、Oracle等数据库,SQLite的体积小

    2024年02月08日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包