png图片,背景替换成无颜色背景

实验需要,加上好奇,使用libpng库将png文件的背景,由黑色,替换成无背景颜色。效果如下图:

替换前:

替换后:

黑色背景都没了,只剩下白色了,看不出来。。。。。。

步骤:

1. 下载png相关库,libpng,以及zlib压缩解压缩文件

  libpng官网下载,Ubuntu下zlib下载安装: sudo apt-get install zlib1-dev

2. 代码:

  

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <png.h>
  5
  6
  7 #define PNG_BYTES_TO_CHECK    8
  8 #define HAVE_ALPHA            1
  9 #define NOT_HAVE_ALPHA        0
 10
 11 typedef struct _pic_data pic_data;
 12 struct _pic_data {
 13     int width, height;     //长宽
 14     int bit_depth;            //位深度
 15     int alpha_flag;        //是否有透明通道
 16     unsigned char *rgba;//实际rgb数据
 17 };
 18
 19 int check_is_png(FILE **fp, const char *filename) //检查是否png文件
 20 {
 21     char checkheader[PNG_BYTES_TO_CHECK]; //查询是否png头
 22     *fp = fopen(filename, "rb");
 23     if (*fp == NULL) {
 24         printf("open failed ...1\n");
 25         return -1;
 26     }
 27     if (fread(checkheader, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) //读取png文件长度错误直接退出
 28         return 0;
 29     return png_sig_cmp(checkheader, 0, PNG_BYTES_TO_CHECK); //0正确, 非0错误
 30 }
 31
 32 int decode_png(const char *filename, pic_data *out) //取出png文件中的rgb数据
 33 {
 34     png_structp png_ptr; //png文件句柄
 35     png_infop    info_ptr;//png图像信息句柄
 36     int ret;
 37     FILE *fp;
 38     if (check_is_png(&fp, filename) != 0) {
 39         printf("file is not png ...\n");
 40         return -1;
 41     }
 42     printf("launcher[%s] ...\n", PNG_LIBPNG_VER_STRING); //打印当前libpng版本号
 43
 44     //1: 初始化libpng的数据结构 :png_ptr, info_ptr
 45     png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 46     info_ptr = png_create_info_struct(png_ptr);
 47
 48     //2: 设置错误的返回点
 49     setjmp(png_jmpbuf(png_ptr));
 50     rewind(fp); //等价fseek(fp, 0, SEEK_SET);
 51
 52     //3: 把png结构体和文件流io进行绑定
 53     png_init_io(png_ptr, fp);
 54     //4:读取png文件信息以及强转转换成RGBA:8888数据格式
 55     png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //读取文件信息
 56     int channels, color_type;
 57     channels     = png_get_channels(png_ptr, info_ptr); //通道数量
 58     color_type     = png_get_color_type(png_ptr, info_ptr);//颜色类型
 59     out->bit_depth = png_get_bit_depth(png_ptr, info_ptr);//位深度
 60     out->width      = png_get_image_width(png_ptr, info_ptr);//宽
 61     out->height  = png_get_image_height(png_ptr, info_ptr);//高
 62
 63     //if(color_type == PNG_COLOR_TYPE_PALETTE)
 64     //    png_set_palette_to_rgb(png_ptr);//要求转换索引颜色到RGB
 65     //if(color_type == PNG_COLOR_TYPE_GRAY && out->bit_depth < 8)
 66     //    png_set_expand_gray_1_2_4_to_8(png_ptr);//要求位深度强制8bit
 67     //if(out->bit_depth == 16)
 68     //    png_set_strip_16(png_ptr);//要求位深度强制8bit
 69     //if(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
 70     //    png_set_tRNS_to_alpha(png_ptr);
 71     //if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
 72     //    png_set_gray_to_rgb(png_ptr);//灰度必须转换成RG
 73     printf("channels = %d color_type = %d bit_depth = %d width = %d height = %d ...\n",
 74             channels, color_type, out->bit_depth, out->width, out->height);
 75
 76     int i, j, k;
 77     int size, pos = 0;
 78     int temp;
 79
 80     //5: 读取实际的rgb数据
 81     png_bytepp row_pointers; //实际存储rgb数据的buf
 82     row_pointers = png_get_rows(png_ptr, info_ptr); //也可以分别每一行获取png_get_rowbytes();
 83     size = out->width * out->height; //申请内存先计算空间
 84     if (channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { //判断是24位还是32位
 85         out->alpha_flag = HAVE_ALPHA; //记录是否有透明通道
 86         size *= (sizeof(unsigned char) * 4); //size = out->width * out->height * channel
 87         out->rgba = (png_bytep)malloc(size);
 88         if (NULL == out->rgba) {
 89             printf("malloc rgba faile ...\n");
 90             png_destroy_read_struct(&png_ptr, &info_ptr, 0);
 91             fclose(fp);
 92             return -1;
 93         }
 94         //从row_pointers里读出实际的rgb数据出来
 95         temp = channels - 1;
 96         for (i = 0; i < out->height; i++)
 97             for (j = 0; j < out->width * 4; j += 4)
 98                 for (k = temp; k >= 0; k--)
 99                     out->rgba[pos++] = row_pointers[i][j + k];
100     } else if (channels == 3 || color_type == PNG_COLOR_TYPE_RGB) { //判断颜色深度是24位还是32位
101         out->alpha_flag = NOT_HAVE_ALPHA;
102         size *= (sizeof(unsigned char) * 3);
103         out->rgba = (png_bytep)malloc(size);
104         if (NULL == out->rgba) {
105             printf("malloc rgba faile ...\n");
106             png_destroy_read_struct(&png_ptr, &info_ptr, 0);
107             fclose(fp);
108             return -1;
109         }
110         //从row_pointers里读出实际的rgb数据
111         temp = (3 * out->width);
112         for (i = 0; i < out->height; i ++) {
113             for (j = 0; j < temp; j += 3) {
114                 out->rgba[pos++] = row_pointers[i][j+2];
115                 out->rgba[pos++] = row_pointers[i][j+1];
116                 out->rgba[pos++] = row_pointers[i][j+0];
117             }
118         }
119     } else return -1;
120     //6:销毁内存
121     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
122     fclose(fp);
123     //此时, 我们的out->rgba里面已经存储有实际的rgb数据了
124     //处理完成以后free(out->rgba)
125     return 0;
126 }
127
128 int RotationRight90(unsigned char * src, int srcW, int srcH, int channel) //顺时针旋转90度
129 {
130     unsigned char * tempSrc = NULL; //临时的buf用来记录原始的图像(未旋转之前的图像)
131     int mSize = srcW * srcH * sizeof(char) * channel;
132     int i = 0;
133     int j = 0;
134     int k = 0;
135     int l = 3;
136     int desW = 0;
137     int desH = 0;
138
139     desW = srcH;
140     desH = srcW;
141
142     tempSrc = (unsigned char *)malloc(sizeof(char) * srcW * srcH * channel);
143     memcpy(tempSrc, src, mSize); //拷贝原始图像至tempbuf
144     for(i = 0; i < desH; i ++)
145     {
146         for(j = 0; j < desW; j ++)
147         {
148             for(k = 0; k < channel; k ++)
149             {
150                 src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - j) * srcW + i) * channel + k]; //替换像素
151             }
152         }
153     }
154     free(tempSrc);
155     return 0;
156 }
157
158 int write_png_file(const char *filename , pic_data *out) //生成一个新的png图像
159 {
160     png_structp png_ptr;
161     png_infop     info_ptr;
162     png_byte color_type;
163     png_bytep * row_pointers;
164     FILE *fp = fopen(filename, "wb");
165     if (NULL == fp) {
166         printf("open failed ...2\n");
167         return -1;
168     }
169     //1: 初始化libpng结构体
170     png_ptr    = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
171     if (!png_ptr) {
172         printf("png_create_write_struct failed ...\n");
173         return -1;
174     }
175     //2: 初始化png_infop结构体 ,
176     //此结构体包含了图像的各种信息如尺寸,像素位深, 颜色类型等等
177     info_ptr = png_create_info_struct(png_ptr);
178     if (!info_ptr) {
179         printf("png_create_info_struct failed ...\n");
180         return -1;
181     }
182     //3: 设置错误返回点
183     if (setjmp(png_jmpbuf(png_ptr))) {
184         printf("error during init_io ...\n");
185         return -1;
186     }
187     //4:绑定文件IO到Png结构体
188     png_init_io(png_ptr, fp);
189     if (setjmp(png_jmpbuf(png_ptr))) {
190         printf("error during init_io ...\n");
191         return -1;
192     }
193     if (out->alpha_flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
194     else color_type = PNG_COLOR_TYPE_RGB;
195     //5:设置以及写入头部信息到Png文件
196     png_set_IHDR(png_ptr, info_ptr, out->width, out->height, out->bit_depth,
197     PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
198     png_write_info(png_ptr, info_ptr);
199     if (setjmp(png_jmpbuf(png_ptr))) {
200         printf("error during init_io ...\n");
201         return -1;
202     }
203     int channels, temp;
204     int i, j, pos = 0;
205     if (out->alpha_flag == HAVE_ALPHA) {
206         channels = 4;
207         temp = (4 * out->width);
208         printf("have alpha ...\n");
209     } else {
210         channels = 4;
211         temp = (4 * out->width);
212         printf("not have alpha ...\n");
213     }
214     // 顺时针旋转90度 , 旋转完了一定要把width 和height调换 不然得到的图像是花的  旋转三次就是逆时针旋转一次
215     //RotationRight90(out->rgba, out->width, out->height, channels);
216     //RotationRight90(out->rgba, out->height, out->width, channels);
217     //RotationRight90(out->rgba, out->width, out->height, channels);
218     row_pointers = (png_bytep*)malloc(out->height * sizeof(png_bytep));
219     for (i = 0; i < out->height; i++) {
220         row_pointers[i] = (png_bytep)malloc(temp* sizeof(unsigned char));
221         for (j = 0; j < temp; j += channels) {
222             if (channels == 4) {
223                 if (out->alpha_flag == HAVE_ALPHA)
224                 row_pointers[i][j+3] = out->rgba[pos++];
225                 //row_pointers[i][j+3] = 0x00;
226                 row_pointers[i][j+2] = out->rgba[pos++];
227                 row_pointers[i][j+1] = out->rgba[pos++];
228                 row_pointers[i][j+0] = out->rgba[pos++];
229                 //printf("----    i = %d, j = %d, %d, %d, %d, %d\n", i, j, row_pointers[i][j + 0], row_pointers[i][j + 1],row_pointers[i][j + 2],row_pointers[i][j + 3]);
230                 if((row_pointers[i][j+0] + row_pointers[i][j+1] + row_pointers[i][j+2]) < 100)
231                 {
232                     row_pointers[i][j+3] = 0x00;
233                     row_pointers[i][j+2] = 0x00;
234                     row_pointers[i][j+1] = 0x00;
235                     row_pointers[i][j+0] = 0x00;
236
237                 }
238                 else
239                 {
240                     row_pointers[i][j+3] = 0xff;
241                     row_pointers[i][j+2] = 0xff;
242                     row_pointers[i][j+1] = 0xff;
243                     row_pointers[i][j+0] = 0xff;
244                 }
245                 //printf("----    i = %d, j = %d, %d, %d, %d, %d\n", i, j, row_pointers[i][j + 0], row_pointers[i][j + 1],row_pointers[i][j + 2],row_pointers[i][j + 3]);
246             } else {
247                 row_pointers[i][j+2] = out->rgba[pos++];
248                 row_pointers[i][j+1] = out->rgba[pos++];
249                 row_pointers[i][j+0] = out->rgba[pos++];
250                 if((row_pointers[i][j+0] + row_pointers[i][j+1] + row_pointers[i][j+2]) < 30)
251                 {
252                     row_pointers[i][j+3] = 0x00;
253                     row_pointers[i][j+2] = 0x00;
254                     row_pointers[i][j+1] = 0x00;
255                     row_pointers[i][j+0] = 0x00;
256
257                 }
258                 else
259                 {
260                     row_pointers[i][j+3] = 0xff;
261                     row_pointers[i][j+2] = 0xff;
262                     row_pointers[i][j+1] = 0xff;
263                     row_pointers[i][j+0] = 0xff;
264                 }
265             //    printf("++++    i = %d, j = %d, %d, %d, %d, %d\n", i, j, row_pointers[i][j + 0], row_pointers[i][j + 1],row_pointers[i][j + 2],row_pointers[i][j + 3]);
266             }
267         }
268     }
269     //6: 写入rgb数据到Png文件
270     png_write_image(png_ptr, (png_bytepp)row_pointers);
271     if (setjmp(png_jmpbuf(png_ptr))) {
272         printf("error during init_io ...\n");
273         return -1;
274     }
275     //7: 写入尾部信息
276     png_write_end(png_ptr, NULL);
277     //8:释放内存 ,销毁png结构体
278     for (i = 0; i < out->height; i ++)
279         free(row_pointers[i]);
280     free(row_pointers);
281     png_destroy_write_struct(&png_ptr, &info_ptr);
282     fclose(fp);
283     return 0;
284 }
285
286 int main(int argc, char **argv)
287 {
288     pic_data out;
289     if (argc == 3) {
290         decode_png(argv[1], &out);
291         write_png_file(argv[2], &out);
292         free(out.rgba);
293     } else {
294         puts("please input two file, \nargv[1]:source.png argv[2]:dest.png");
295     }
296     return 0;
297 }

参考:https://blog.csdn.net/wang93IT/article/details/85003730

原文地址:https://www.cnblogs.com/hanrp/p/11419147.html

时间: 2024-10-09 07:28:07

png图片,背景替换成无颜色背景的相关文章

应用启动时将白屏背景替换成图片/颜色/动画等 仅供参考

1.创建自己的主题样式(style) 在vules资源目录下的style中创建一个样式 <style name="MyTheme" parent="Theme.AppCompat.NoActionBar"> //parent是必须(一般是系统提供的)的 (没有的话主题样式就没效果,遇到的就是这样,说错了莫怪) <item name="android:windowBackground">@drawable/guide_bg&

mfc中 控件 对话框 添加颜色 背景图片

1 设置对话框透明 在设置控件颜色中要使用 nCtlColor Contains one of the following values, specifying the type of control: CTLCOLOR_BTN   Button control CTLCOLOR_DLG   Dialog box CTLCOLOR_EDIT   Edit control CTLCOLOR_LISTBOX   List-box control CTLCOLOR_MSGBOX   Message b

css3(边框,背景,字体,颜色之RGBA与透明度opcity,图片和渐变颜色)

边框: 盒子圆角:border-radius:5px / 20%: border-radius:5px 4px 3px 2px; 左上,右上,右下,左下. 盒子阴影: box-shadow: box-shadow:x轴偏移量 y轴偏移量 阴影模糊半径(阴影颜色的模糊程度)  阴影扩展半径 阴影颜色  投影方式注意:inset 是指阴影在盒子内部,默认在外部,inset写到第一个或者最后一个参数位置,其他位置是无效的. 值有3个时,表示距离左侧.距离上侧.影子颜色: 值有4个时,表示距离左侧.距离

获取bing图片并自动设置为电脑桌面背景(使用 URLDownloadToFile API函数)

众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找到图片的下载链接,并下载之 将图片设置为桌面背景(也有部分浏览器支持直接在网页中右击图片设置为壁纸) 可能你还会删除下载下来的图片 作为一枚coder,你不会觉得麻烦嘛?至少需要三个步骤呢! So...我就用C++语言写了一个小程序,用于获取bing网站的图片,并将其设置为桌面背景.整个过程只需要点

一个解决chrome浏览器下input标签当autocomplete的时候背景变黄色同时input背景图片消失方案

最近在改一个bug即如标题所讲的一样,chrome浏览器下当input标签开启autocomplete的时候input的背景颜色变黄同时在input的背景图片也被覆盖了.为此百度了好久发现网上说的使用js来append操作,亲测了都不管用.除非把autocomplete=“off”关了,但这就不符合需求了 如图 网上说的改变-webkit-autofill的阴影背景是可以去除黄色背景的,但是图片依旧被覆盖了. input:-webkit-autofill{ box-shadow:0 0 0px

【JavaScript】轻松更改网页背景与字体的颜色

JavaScript,通过点击按钮更改网页背景与字体的颜色,网页中有N个改变颜色的按钮,点击不同的按钮,网页的字体与背景就会改变成不同的颜色.很简单的JavaScript小程序. 一.基本目标 一打开网页首先提示问候信息"你好" 网页中有N个改变颜色的按钮,其中返回是返回网页的默认颜色,背景是白的,字体是黑的 点击不同的按钮,网页的字体与背景就会改变成不同的颜色. 本来想做出彩虹起色的,但原理完全一样就不多写按钮了. 二.基本思想 关键是对body标签与字体js提供id,使其在js中得

【iOS开发-31】UITabBar背景、icon图标颜色、被选中背景设置以及隐藏UITabBar的两种方式

一.对UITabBar背景和icon图标的一些设置 (1)由于直接给UITabBar设置的背景颜色显示的不纯.半透明的感觉,所以,有时候我们能够直接利用纯色的图片作为背景达到想要的效果. (2)给icon图片改变颜色也是重要的有用方法之中的一个,默认的时蓝色. 在AppDelegate.m文件里:(1个导航控制器和5个视图控制器) - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSD

pushbutton添加圆形图片(去掉原来button的背景)

    QIcon next("pic/next.png");     ui->nextbtn->setIcon(next);     ui->nextbtn->setIconSize(ui->nextbtn->size());//将图片大小设置成button的大小     ui->nextbtn->setFlat(true);//去掉原来pushbutton的背景                         注意:next.png放

兼容多种浏览器的渐变颜色背景

经常有一些时候需要使用渐变背景,使用长条图片有点太不高大上了,于是自己写了个小例子,兼容多浏览器就要为每一个浏览器写对应的 CSS,太低版本的浏览器只能使用图片做背景. 下面是当前五大浏览器对 gradient 的支持 Css代码   <style type="text/css" media="screen"> #gradient { width: 200px; height: 200px; /* 如果浏览器不支持渐变,使用图像作为背景 */ backg