操作png图片文件——libpng库——C++

news/2024/7/3 0:01:42

文章目录

    • 读取png、写入png
    • 读取一个png文件
    • 写入一个png
    • 创建一个空白png,改变某个像素点颜色,保存
    • 读取一个png,改变指定像素点颜色,保存

读取png、写入png

#include <png.h>
int main(int argc, char** argv)
{
        png_image image; /* The control structure used by libpng */

        /* Initialize the 'png_image' structure. */
        memset(&image, 0, (sizeof image));
        image.version = PNG_IMAGE_VERSION;

        /* The first argument is the file to read: */
        if (png_image_begin_read_from_file(&image, "./test_500.png"))
        {
            png_bytep buffer; 
            image.format = PNG_FORMAT_RGBA;

            buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image));

            if (buffer != NULL && png_image_finish_read(&image, NULL/*background*/, buffer, 0/*row_stride*/, NULL/*colormap*/) != 0)
            {
                if (png_image_write_to_file(&image, "./res.png", 0/*convert_to_8bit*/,buffer, 0/*row_stride*/, NULL/*colormap*/) != 0)
                {
                    exit(0);
                }
            }
            else
            {
                if (buffer == NULL)
                    png_image_free(&image);
                else
                    free(buffer);
            }
        }

}

读取一个png文件

#include <png.h>
#include <setjmp.h>
#ifndef png_jmpbuf
#define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf)
#endif
int main(int argc, char** argv)
{

    // FILE读取一个png
    std::string file_name = "./test_500.png";
  
    FILE* fp;
    if (fopen_s(&fp,file_name.c_str(), "rb")!=0)
    {
        std::cout << "打开文件失败" << std::endl;
        return 0;
    }

    // 创建libpng库依赖的解码示例上下文
    png_structp png_ptr;
    png_infop info_ptr;
    int sig_read = 0;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_ptr == NULL)
    {
        fclose(fp);
        return 0;
    }
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        return 0;
    }
    // 设置输入流
    png_init_io(png_ptr, fp);
    //png_set_sig_bytes(png_ptr, sig_read);
    // 读取png文件头
    png_read_info(png_ptr, info_ptr);
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
        &interlace_type, NULL, NULL);

    return 0;
 }

写入一个png

创建一个空白png,改变某个像素点颜色,保存

/// 灰色背景的测试成功
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#define WIDTH  500  // 图像宽度
#define HEIGHT 500  // 图像高度
void set_pixel_color(png_bytep row_pointers[], int row, int col, png_byte red, png_byte green, png_byte blue) {
    png_bytep row_pointer = row_pointers[row];
    png_bytep pixel = &(row_pointer[col * 3]);  // 每个像素由3个字节表示(红、绿、蓝)

    pixel[0] = red;
    pixel[1] = green;
    pixel[2] = blue;
}
int main() {
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep row_pointers[HEIGHT];

    // 创建一个空白的PNG图像
    for (int row = 0; row < HEIGHT; ++row) {
        row_pointers[row] = (png_byte*)malloc(3 * WIDTH);
    }

    // 填充某个像素点的颜色
    int target_row = 50;
    int target_col = 50;
    png_byte target_red = 255;   // 红色分量
    png_byte target_green = 0;   // 绿色分量
    png_byte target_blue = 0;    // 蓝色分量

    set_pixel_color(row_pointers, target_row, target_col, target_red, target_green, target_blue);

    // 将图像数据写入到PNG文件中
    FILE* fp;
    if (fopen_s(&fp,"./output.png", "wb") != 0)
    {
        std::cout << "打开文件失败" << std::endl;
        return 0;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);
    png_init_io(png_ptr, fp);
    png_set_IHDR(png_ptr, info_ptr, WIDTH, HEIGHT, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    png_write_info(png_ptr, info_ptr);
    png_write_image(png_ptr, row_pointers);
    png_write_end(png_ptr, NULL);

    // 释放内存和关闭文件
    for (int row = 0; row < HEIGHT; ++row) {
        free(row_pointers[row]);
    }
    fclose(fp);

    return 0;
}

读取一个png,改变指定像素点颜色,保存

#include <png.h>
#include <setjmp.h>
#ifndef png_jmpbuf
#define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf)
#endif
void set_pixel_color(png_bytep* row_pointers, int row, int col, png_byte red, png_byte green, png_byte blue, png_byte alpha=1) 
{
    png_bytep row_pointer = row_pointers[row];
    png_bytep pixel = &(row_pointer[col * 4]);  // 每个像素由4个字节表示(红、绿、蓝、透明度)

    pixel[0] = red;
    pixel[1] = green;
    pixel[2] = blue;
    pixel[3] = alpha;
}

int main(int argc, char** argv)
{
    // FILE读取一个png
    std::string file_name = "./test_500.png";

    FILE* fp;
    if (fopen_s(&fp, file_name.c_str(), "rb") != 0)
    {
        std::cout << "打开文件失败" << std::endl;
        return 0;
    }

    // 创建libpng库依赖的解码示例上下文
    png_structp png_ptr;
    png_infop info_ptr;
    int sig_read = 0;
    png_uint_32 width, height;
    int bit_depth_1, color_type_1, interlace_type_1;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_ptr == NULL)
    {
        fclose(fp);
        return 0;
    }
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        return 0;
    }
    // 设置输入流
    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 0);
    // 读取png文件头
    png_read_info(png_ptr, info_ptr);
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_1, &color_type_1,&interlace_type_1, NULL, NULL);

    int w = png_get_image_width(png_ptr, info_ptr);
    int h = png_get_image_height(png_ptr, info_ptr);
    png_byte color_type = png_get_color_type(png_ptr, info_ptr);
    png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // 读取PNG图像像素数据
    png_bytep* row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
    for (int row = 0; row < height; ++row) {
        row_pointers[row] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr));
    }
    png_read_image(png_ptr, row_pointers);


    // 替换某个像素点的颜色
    int target_row = 50;
    int target_col = 50;
    png_byte target_red = 0;   // 红色分量
    png_byte target_green = 0;   // 绿色分量
    png_byte target_blue = 0;    // 蓝色分量
    png_byte target_alpha = 0;    // 透明度


    set_pixel_color(row_pointers, target_row, target_col, target_red, target_green, target_blue,target_alpha);

    //===========================================================================

    // 写入PNG图像文件
     FILE* output_fp;
    if (fopen_s(&output_fp, "./resule.png", "wb") != 0)
    {
        std::cout << "打开文件失败" << std::endl;
        return 0;
    }
    png_structp png_write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_write_ptr == NULL)
    {
        std::cout << "png_create_read_struct failed" << std::endl;
    }
    png_infop png_w_info = png_create_info_struct(png_write_ptr);
    if (png_write_info == NULL)
    {
        std::cout << "png_create_info_struct  failed" << std::endl;
    }
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_write_ptr, &png_w_info, NULL);
        fclose(fp);
        return 0;
    }
    png_init_io(png_write_ptr, output_fp);
    png_set_IHDR(png_write_ptr, png_w_info, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    png_write_info(png_write_ptr, png_w_info);
    png_write_image(png_write_ptr, row_pointers);
    png_write_end(png_write_ptr, NULL);


    // 释放内存和关闭文件
        // 释放内存和关闭文件
    for (int row = 0; row < height; ++row) {
        free(row_pointers[row]);
    }
    free(row_pointers);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    png_destroy_write_struct(&png_write_ptr, &png_w_info);
    fclose(fp);
    fclose(output_fp);

    return 0;
}

http://lihuaxi.xjx100.cn/news/1372168.html

相关文章

ChatGPT vs. 之前版本:性能与表现的对比

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

IDEA maven 命令行打包 和指令打包的区别

IDEA maven 命令行打包 和指令打包的区别 背景除此之外的打包命令还有如下&#xff1a;相比之下这样打包的好处呢&#xff1a;1. 系统独立性&#xff1a;2. 构建配置灵活性&#xff1a;3. 可移植性&#xff1a;4. 可扩展性&#xff1a; 背景 今天在项目打包的时候被大佬指指点点…

删除Windows顽固启动项Program

卸载软件之后可能会遇到任务管理器中启动项显示有Program这种无效项目的情况 无效项目如图所示: 解决方法 打开注册表 Win R 打开注册表后定位到 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run 可以直接复制粘贴到地址栏进行跳…

【Nodejs】Node.js简介

1.前言 Node 的重要性已经不言而喻&#xff0c;很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外&#xff0c;目前最为流行的 Web 开发模式是前后端分离的形式&#xff0c;即前端开发者与后端开发者在自己喜…

[Android 13]Input系列--触摸事件在应用进程的分发和处理

hongxi.zhu 2023-7-21 Android 13 前面我们已经梳理了input事件在native层的传递&#xff0c;这一篇我们接着探索input事件在应用中的传递与处理&#xff0c;我们将按键事件和触摸事件分开梳理&#xff0c;这一篇就只涉及触摸事件。 一、事件的接收 从前面的篇幅我们知道&…

装饰模式-扩展系统功能

买了新车后&#xff0c;不少人会对车进行装饰&#xff0c;比如给车贴膜&#xff0c;喷上骚粉的漆等。某天&#xff0c;小李和小张都买了辆车&#xff0c;小李想给车贴膜&#xff0c;小张想给车先喷漆然后再贴膜。现在中的做法是&#xff0c;把车开到改装店&#xff0c;如果要喷…

【测试笔记】示波器的使用示例(多图形说明,少文字描述)

示波器的使用示例 一、示波器图样二、总体介绍三、分布介绍3.1 分段线设置3.2 单通道波形调整3.3 整体波形图像调整3.4 滚动模式3.5 测量显示选择3.6 储存选择3.7 触发捕获模式选择 前言&#xff1a;本篇文章是我使用示波器后的一个功能记录&#xff0c;多为常用功能记录&#…

七大设计模式原则

1、开闭原则&#xff08;Open-closed Principle&#xff09; 开闭原则&#xff0c;是面向设计中最基础的设计原则。 一个软件实体类、模块、函数应该对扩展开放、对修改关闭。 强调的是用抽象构建框架&#xff0c;用实现扩展细节。可以提高软件系统的可复用性和可维护性。 实…