GTK+中文社区(gtk.awaysoft.com)

 找回密码
 马上加入

QQ登录

只需一步,快速开始

查看: 6591|回复: 4

将图片转换成C语言数据文件,然后在程序中调用重现图片

[复制链接]

该用户从未签到

发表于 2011-5-8 18:10:57 | 显示全部楼层 |阅读模式
将图片转换为数据(imgtodata)
第一步,先获取图片的数据信息:
  1. pixbuf = gdk_pixbuf_new_from_file(open_filename, NULL);
  2.     data = gdk_pixbuf_get_pixels(pixbuf);//获得图片像素的数据,数据类型为guchar
  3.     width = gdk_pixbuf_get_width(pixbuf);
  4.     height = gdk_pixbuf_get_height(pixbuf);
  5.     stride = gdk_pixbuf_get_rowstride(pixbuf);//一行像素所占的字节数。
  6.     n_channels = gdk_pixbuf_get_n_channels (pixbuf);//如果图片为RGB格式即此值为3,如果是RGBA格式则此值为4
复制代码
由于本例中图片再现是用cairo_image_surface_create_for_data() 来实现的,数据的排列方式跟PIXBUF不一样,所以要做一下处理。
第二步,数据重新排列:
  1. bytesperpixel = n_channels;
  2.     cairostride = stride;
  3.     if(n_channels == 3)
  4.     {   
  5.         bytesperpixel += 1;
  6.         cairostride = width * 4;
  7.     }
  8.     if(cairodata != NULL)
  9.         g_free(cairodata);
  10.     cairodata = g_malloc0(cairostride*height);
  11.     for(y = 0; y < height; y++)
  12.     {
  13.         for(x = 0; x < width; x++)
  14.         {
  15.             pdata = data + y * stride + x * n_channels;
  16.             pcdata = cairodata + y * cairostride + x * bytesperpixel;
  17.             pcdata[0] = pdata[2];
  18.             pcdata[1] = pdata[1];
  19.             pcdata[2] = pdata[0];
  20.             if(n_channels == bytesperpixel)
  21.                 pcdata[3] = pdata[3];
  22.         }
  23.     }
复制代码
至此cairodata就得到我们所要的像素数据。
第三步,就是将cairodata保存到文件。
  1. FILE* fp = NULL;
  2.     GtkWidget *message_dlg;
  3.     gint return_value;
  4.     gchar **dcharTemp;
  5.     GString *gstringTemp;
  6.     gint i, j, k;
  7.     guchar tempchar[2];
  8.    
  9.     if ((fp = fopen(filename,"rb")) != NULL)
  10.     {
  11.         fclose(fp);
  12.         message_dlg = gtk_message_dialog_new(GTK_WINDOW(NULL),GTK_DIALOG_MODAL,
  13.                 GTK_MESSAGE_QUESTION,GTK_BUTTONS_YES_NO,_("Over write the file?"));
  14.         return_value = gtk_dialog_run(GTK_DIALOG(message_dlg));
  15.         gtk_widget_destroy(message_dlg);
  16.         if( return_value != GTK_RESPONSE_YES)
  17.             return -2;
  18.     }
  19.     if ((fp = fopen(filename,"wb")) == NULL)
  20.     {
  21. //        g_warning("error open %s\n",filename);
  22.         message_dlg = gtk_message_dialog_new(GTK_WINDOW(NULL),GTK_DIALOG_MODAL,
  23.                 GTK_MESSAGE_INFO,GTK_BUTTONS_OK,_("Can not save file."));        
  24.         gtk_dialog_run(GTK_DIALOG(message_dlg));
  25.         gtk_widget_destroy(message_dlg);
  26.         return -1;
  27.     }
  28.     fputs("const unsigned char ",fp);
  29.     dcharTemp = g_strsplit(g_filename_display_basename(filename),".",-1);
  30.     gstringTemp = g_string_new(NULL);
  31.     g_string_printf(gstringTemp,"%s_mark%d[] = {\n",*dcharTemp,width);
  32.     fputs(gstringTemp->str, fp);
  33.     for(i = 0; i < height; i++)
  34.     {
  35.         g_string_free(gstringTemp, TRUE);
  36.         gstringTemp = g_string_new(NULL);
  37.         for(j = 0; j < width; j++)
  38.         {
  39.             pcdata = cairodata + i * cairostride + j * bytesperpixel;
  40.             g_string_append_printf(gstringTemp, "0x%x, 0x%x, 0x%x, 0x%x, ",pcdata[0],pcdata[1],pcdata[2],pcdata[3]);
  41.         }
  42.         g_string_append_printf(gstringTemp, "\n");
  43.         fputs(gstringTemp->str, fp);
  44.     }
  45.     fseek(fp, -3, SEEK_CUR);
  46.     fputs("\n};\n",fp);
  47.     fclose(fp);
  48.     g_string_free(gstringTemp, TRUE);
复制代码
至此,转换功能完成。
下面是如何将数据重现为图片(datatoimg)。
第一步,建立一个新工程,转换生成的*.c(如本例中生成gtk_logo_rgb.c)加到工程中。
第二步,在drawingarea的“expose“回调中重现图片。
  1. cairo_t *cr;
  2.     cairo_surface_t *surface;
  3.     gint cairosurfacex, cairosurfacey;
  4.     gint mark_width = 107;
  5.     gint mark_height = 140;
  6.     gint mark_stride = 428;  /* BGRA is 4 channels, so width*channels=107*4=428*/
  7.    
  8.     cr = gdk_cairo_create(widget->window);
  9.     surface = cairo_image_surface_create_for_data(gtk_logo_rgb_mark107,CAIRO_FORMAT_ARGB32,mark_width,mark_height,mark_stride);
  10.     cairosurfacex = MAX (((widget->allocation.width-mark_width)/2), 0);
  11.     cairosurfacey = MAX (((widget->allocation.height-mark_height)/2), 0);
  12.     cairo_set_source_surface (cr, surface, cairosurfacex, cairosurfacey);
  13.     cairo_paint(cr);
  14.     cairo_destroy(cr);
  15.     cairo_surface_destroy(surface);
复制代码

附上源代码,编程环境,windowxp,devcpp,gtk-2.12.9-dev

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?马上加入

x

评分

参与人数 1 +11 收起 理由
Tom + 11 资源分享

查看全部评分

该用户从未签到

发表于 2011-5-9 19:22:51 | 显示全部楼层
学习 学习啊

该用户从未签到

发表于 2012-3-12 20:45:27 | 显示全部楼层
想学

该用户从未签到

发表于 2012-3-20 18:21:51 | 显示全部楼层
谢谢

该用户从未签到

发表于 2012-9-26 02:12:38 | 显示全部楼层
学习了
*滑块验证:
您需要登录后才可以回帖 登录 | 马上加入

本版积分规则

申请友链|Archiver|小黑屋|手机版|GTK+中文社区 ( 粤ICP备13080851号 )

我要啦免费统计

GMT+8, 2024-4-20 05:47 , Processed in 0.041309 second(s), 8 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表