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

3 篇文章 0 订阅

读取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;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值