centos7 C++ 调用libpng png转bmp

2024-03-06 23:18
文章标签 c++ centos7 调用 png bmp libpng

本文主要是介绍centos7 C++ 调用libpng png转bmp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    宽度不为4的倍数的png自动转为4的倍数的png,即扩展bmp的像素了。支持3通道(RGB)的png图片以及4通道(RGBA)的png图片解析。

    下载地址:https://download.csdn.net/download/sz76211822/10800747

    

#ifndef __PARSE_PNG__
#define __PARSE_PNG__class ParsePng
{
public:ParsePng();~ParsePng();bool Parse(const char *pstrFilePath, unsigned char* pBitmapBuffer, long nBufferSize, long& nWidth, long& nHeight);private:void write_bmp_header(long nWidth, long nHeight, long nDepth);private:long m_nLenHeader;unsigned char* m_pImage;unsigned char* m_pCache;
};#endif

源文件:

#include "ParsePng.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>extern "C"{#include "include/png.h"
}#define MAX_LINE_SIZE           2  * 1024 * 1024
#define MAX_IMAGE_SIZE          20 * 1024 * 1024#pragma pack(2)
typedef struct BITMAPFILEHEADER {u_int16_t bfType;u_int32_t bfSize;u_int16_t bfReserved1;u_int16_t bfReserved2;u_int32_t bfOffBits;
} BITMAPFILEHEADER;typedef struct BITMAPINFOHEADER {u_int32_t biSize;u_int32_t biWidth;u_int32_t biHeight;u_int16_t biPlanes;u_int16_t biBitCount;u_int32_t biCompression;u_int32_t biSizeImage;u_int32_t biXPelsPerMeter;u_int32_t biYPelsPerMeter;u_int32_t biClrUsed;u_int32_t biClrImportant;
} BITMAPINFODEADER;ParsePng::ParsePng()
{m_nLenHeader = 0;m_pImage = NULL;while(!m_pImage){try{m_pImage = new unsigned char[MAX_IMAGE_SIZE];}catch(...){}}m_pCache = NULL;while(!m_pCache){try{m_pCache = new unsigned char[MAX_LINE_SIZE];}catch(...){}}
}
ParsePng::~ParsePng()
{if(m_pImage){delete[] m_pImage;m_pImage = NULL;}if(m_pCache){delete[] m_pCache;m_pCache = NULL;}
}
void ParsePng::write_bmp_header(long nWidth, long nHeight, long nDepth)
{struct BITMAPFILEHEADER bfh;struct BITMAPINFOHEADER bih;unsigned long headersize = 0;unsigned long filesize = 0;if(nWidth % 4 != 0){//4字节对齐nWidth += 4 - nWidth % 4;}if (nDepth == 1) {headersize = 14 + 40 + 256 * 4;filesize = headersize + nWidth * nHeight;}if (nDepth == 3) {headersize = 14 + 40;filesize = headersize + nWidth * nHeight * nDepth;}memset(&bfh, 0, sizeof(struct BITMAPFILEHEADER));memset(&bih, 0, sizeof(struct BITMAPINFOHEADER));//写入比较关键的几个bmp头参数bfh.bfType = 0x4D42;bfh.bfSize = filesize;bfh.bfOffBits = headersize;bih.biSize = 40;bih.biWidth = nWidth;bih.biHeight = nHeight;bih.biPlanes = 1;bih.biBitCount = (unsigned short)nDepth * 8;bih.biSizeImage = nWidth * nHeight * nDepth;memcpy(m_pImage, &bfh, sizeof(struct BITMAPFILEHEADER));memcpy(m_pImage + sizeof(struct BITMAPFILEHEADER), &bih, sizeof(struct BITMAPINFOHEADER));if (nDepth == 1) {//灰度图像要添加调色板unsigned char *platte = NULL;while(!platte){try{platte = new unsigned char[256*4];}catch(...){}}unsigned char j = 0;for (int i = 0; i < 1024; i += 4) {platte[i] = j;platte[i+1] = j;platte[i+2] = j;platte[i+3] = 0;j++;}memcpy(m_pImage + sizeof(struct BITMAPFILEHEADER) + sizeof(struct BITMAPINFOHEADER), platte, sizeof(unsigned char) * 1024);m_nLenHeader = sizeof(struct BITMAPFILEHEADER) + sizeof(struct BITMAPINFOHEADER) + sizeof(unsigned char) * 1024;delete[] platte;}else{m_nLenHeader = sizeof(struct BITMAPFILEHEADER) + sizeof(struct BITMAPINFOHEADER);}
}bool ParsePng::Parse(const char *pstrFilePath, unsigned char* pBitmapBuffer, long nBufferSize, long& nWidth, long& nHeight)
{m_nLenHeader = 0;memset(m_pImage, 0, MAX_IMAGE_SIZE);memset(m_pCache, 0, MAX_LINE_SIZE);FILE *pFile = fopen(pstrFilePath, "rb+");if(pFile){//文件打开失败png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);if (png_ptr == NULL){fclose(pFile);return false;}png_infop info_ptr = png_create_info_struct(png_ptr);if (info_ptr == NULL){fclose(pFile);png_destroy_write_struct(&png_ptr,  NULL);return false;}if (setjmp(png_jmpbuf(png_ptr))){//如果程序跑到这里了,那么写入文件时出现了问题fclose(pFile);png_destroy_write_struct(&png_ptr, &info_ptr);return false;}rewind(pFile);png_init_io(png_ptr, pFile);//开始读文件png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);//读文件/*获取宽度,高度,位深,颜色类型*/long nChannel = png_get_channels(png_ptr, info_ptr); //获取通道数long nDepth = png_get_bit_depth(png_ptr, info_ptr); //获取位深int color_type = png_get_color_type(png_ptr, info_ptr); //颜色类型/* row_pointers里边就是rgba数据 */png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);nWidth = png_get_image_width(png_ptr, info_ptr);nHeight = png_get_image_height(png_ptr, info_ptr);long nRemain = 0;if(nWidth % 4 != 0){nRemain = 4 - nWidth % 4;}write_bmp_header(nWidth, nHeight, 3);if(nChannel == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA){/*如果是RGB+alpha通道,或者RGB+其它字节*/for(int i = nHeight - 1; i >= 0; i--){long nOffset = 0;for(int j = 0; j < nWidth * nChannel; j += nChannel){/* 一个字节一个字节的赋值 */m_pCache[nOffset++] = row_pointers[i][j + 2]; // redm_pCache[nOffset++] = row_pointers[i][j + 1]; // greenm_pCache[nOffset++] = row_pointers[i][j + 0];  // blue//m_pCache[j * 4 + 3] = row_pointers[i][j * 4 + 3]; // alpha}for(int i = 0; i < nRemain * 3; i++){//4字节对齐,比如图片宽度是157,那么补到160个像素。bmp每个像素占3个字节,故(160 - 157) * 3 = 9。我这里是补字节数m_pCache[nOffset++] = 0x00;}memcpy(m_pImage + m_nLenHeader, m_pCache, nOffset);m_nLenHeader += sizeof(unsigned char) * nOffset;}fclose(pFile);png_destroy_read_struct(&png_ptr, &info_ptr, 0);//撤销数据占用的内存if(pBitmapBuffer){if(nBufferSize >= m_nLenHeader){memcpy(pBitmapBuffer, m_pImage, m_nLenHeader);}}return true;}else if(nChannel == 3 || color_type == PNG_COLOR_TYPE_RGB){/* 如果是RGB通道 */for(int i = nHeight - 1; i >= 0; i--){long nOffset = 0;for(int j = 0; j < nChannel * nWidth; j += nChannel){/* 一个字节一个字节的赋值 */m_pCache[nOffset++] = row_pointers[i][j + 2]; // redm_pCache[nOffset++] = row_pointers[i][j + 1]; // greenm_pCache[nOffset++] = row_pointers[i][j + 0];  // blue}for(int i = 0; i < nRemain * 3; i++){//4字节对齐,比如图片宽度是157,那么补到160个像素。bmp每个像素占3个字节,故(160 - 157) * 3 = 9。我这里是补字节数m_pCache[nOffset++] = 0x00;}memcpy(m_pImage + m_nLenHeader, m_pCache, nOffset);m_nLenHeader += sizeof(unsigned char) * nOffset;}fclose(pFile);png_destroy_read_struct(&png_ptr, &info_ptr, 0);//撤销数据占用的内存if(pBitmapBuffer){if(nBufferSize >= m_nLenHeader){memcpy(pBitmapBuffer, m_pImage, m_nLenHeader);}}return true;}}return false;
}

 

这篇关于centos7 C++ 调用libpng png转bmp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781675

相关文章

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

Centos7安装Mongodb4

1、下载源码包 curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.1.tgz 2、解压 放到 /usr/local/ 目录下 tar -zxvf mongodb-linux-x86_64-rhel70-4.2.1.tgzmv mongodb-linux-x86_64-rhel70-4.2.1/

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

Centos7安装JDK1.8保姆版

工欲善其事,必先利其器。这句话同样适用于学习Java编程。在开始Java的学习旅程之前,我们必须首先配置好适合的开发环境。 通过事先准备好这些工具和配置,我们可以避免在学习过程中遇到因环境问题导致的代码异常或错误。一个稳定、高效的开发环境能够让我们更加专注于代码的学习和编写,提升学习效率,减少不必要的困扰和挫折感。因此,在学习Java之初,投入一些时间和精力来配置好开发环境是非常值得的。这将为我

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)