fltk动态分配数据显示图像

fltk中在控件上显示图像可以使用生成静态数组的方式,用的时候直接加载显示即可,但是这种方式对于只是开始时显示以后就不用的图像,静态数组不能随后释放,特别是在图像比较大时会占用大量的内存。

可以使用fluid将图像转换的静态数组转换为图像数据,在使用的时候读入,用完之后释放,这样就可以节省一部分资源。

下面是一个将fluid生成的图像数据静态数组转换为数据文件然后在使用时加载的例子。

首先是将静态数组文件读取出来:

  1. size_tparse_imgdata_file(constchar*file_name,unsignedchar*pdata)
  2. {
  3. if(pdata==NULL)
  4. return0;
  5. FILE*fp=fopen(file_name,"rt");
  6. if(fp==NULL)
  7. return0;
  8. if(fseek(fp,0,SEEK_END)!=0)
  9. {
  10. fclose(fp);
  11. return0;
  12. }
  13. longfile_len=ftell(fp);
  14. if(file_len==-1)
  15. {
  16. fclose(fp);
  17. return0;
  18. }
  19. fseek(fp,0,SEEK_SET);
  20. char*temp=newchar[file_len+1];
  21. if(temp==NULL)
  22. {
  23. fclose(fp);
  24. return0;
  25. }
  26. memset(temp,0,file_len+1);
  27. longrd_len=fread(temp,1,file_len,fp);
  28. if(rd_len==0&&ferror(fp)!=0)
  29. {
  30. fclose(fp);
  31. delete[]temp;
  32. return0;
  33. }
  34. size_tcnt=0;
  35. char*beg_pos=strchr(temp,'{');
  36. char*end_pos=strchr(temp,'}');
  37. if(beg_pos==NULL||end_pos==NULL)
  38. {
  39. fclose(fp);
  40. delete[]temp;
  41. return0;
  42. }
  43. charnum_str[5]={0};
  44. for(char*find_pos=++beg_pos;find_pos<end_pos;)
  45. {
  46. if(isdigit(*find_pos))
  47. {
  48. inti=0;
  49. while(isdigit(*find_pos))
  50. num_str[i++]=*find_pos++;
  51. pdata[cnt++]=(unsignedchar)atoi(num_str);
  52. memset(num_str,0,5);
  53. }
  54. else
  55. ++find_pos;
  56. }
  57. fclose(fp);
  58. delete[]temp;
  59. returncnt;
  60. }
size_t parse_imgdata_file(const char *file_name, unsigned char *pdata)
{
	if(pdata == NULL)
		return 0;
	FILE *fp = fopen(file_name, "rt");
	if(fp == NULL)
		return 0;

	if(fseek(fp, 0, SEEK_END) != 0)
	{
		fclose(fp);
		return 0;
	}
	long file_len = ftell(fp);
	if(file_len == -1)
	{
		fclose(fp);
		return 0;
	}
	fseek(fp, 0, SEEK_SET);

	char *temp = new char[file_len+1];
	if(temp == NULL)
	{
		fclose(fp);
		return 0;
	}
	memset(temp, 0, file_len+1);

	long rd_len = fread(temp, 1, file_len, fp);
	if(rd_len==0 && ferror(fp)!=0)
	{
		fclose(fp);
		delete []temp;
		return 0;
	}

	size_t cnt = 0;
	char *beg_pos = strchr(temp, '{');
	char *end_pos = strchr(temp, '}');
	if(beg_pos==NULL || end_pos==NULL)
	{
		fclose(fp);
		delete []temp;
		return 0;
	}

	char num_str[5] = {0};
	for (char *find_pos = ++beg_pos; find_pos<end_pos;)
	{
		if(isdigit(*find_pos))
		{		
			int i=0;
			while(isdigit(*find_pos))
				num_str[i++] = *find_pos++;
			pdata[cnt++] = (unsigned char)atoi(num_str);
			memset(num_str, 0, 5);
		}
		else
			++find_pos;
	}

	fclose(fp);
	delete []temp;
	return cnt;
}


需要注意的是数据区需要在外面分配,因为图像的大小肯定是已知的,所以分配内存不难;

下面是将读取到的数据保存到纯数据文件中(当然可以直接使用上面的程序读取数据然后用,但是有个parse的过程比较慢,所以还是直接保存为数据文件读取的时候比较快一些)。

  1. size_tstore_imgdata(constchar*file_name,unsignedchar*pdata,size_tdata_len)
  2. {
  3. if(pdata==NULL)
  4. return0;
  5. FILE*fp=fopen(file_name,"wb");
  6. if(fp==NULL)
  7. return0;
  8. size_tstore_len=fwrite(pdata,data_len,1,fp);
  9. fclose(fp);
  10. return(store_len==1?data_len:0);
  11. }
size_t store_imgdata(const char *file_name, unsigned char *pdata, size_t data_len)
{
	if(pdata == NULL)
		return 0;
	FILE *fp = fopen(file_name, "wb");
	if(fp == NULL)
		return 0;
	
	size_t store_len = fwrite(pdata, data_len, 1, fp);

	fclose(fp);
	return (store_len==1 ? data_len : 0);
}


最后是使用的时候的读取数据文件的函数:

  1. size_tload_imgdata(constchar*file_name,unsignedchar*pdata,size_tdata_len)
  2. {
  3. if(pdata==NULL)
  4. return0;
  5. FILE*fp=fopen(file_name,"rb");
  6. if(fp==NULL)
  7. return0;
  8. size_tload_len=fread(pdata,data_len,1,fp);
  9. fclose(fp);
  10. return(load_len==1?data_len:0);
  11. }
size_t load_imgdata(const char *file_name, unsigned char *pdata, size_t data_len)
{
	if(pdata == NULL)
		return 0;
	FILE *fp = fopen(file_name, "rb");
	if(fp == NULL)
		return 0;

	size_t load_len = fread(pdata, data_len, 1, fp);

	fclose(fp);
	return (load_len==1 ? data_len : 0);
}

其实函数都比较简单,相比较于使用静态数组的方式加载图像,这种方式会慢一些,但是静态加载在图像太大时,静态编译的栈可能会溢出导致无法编译,需要修改栈大小,而且编译会很慢;这种动态的方式就快多了,当然前期的转换工作需要人工来做。下面是一个测试的例子:

  1. intmain(intargc,char*argv[])
  2. {
  3. size_tsz=175*126*3;
  4. unsignedchar*pdata=newunsignedchar[sz];
  5. size_tlen=load_imgdata("test.dat",pdata,sz);
  6. printf("len=%u\n",len);
  7. Fl::scheme("GTK+");
  8. Fl_Window*win=newFl_Window(800,400,"TabsExample");
  9. {
  10. Fl_Button*btn=newFl_Button(120,140,200,200,"button");
  11. Fl_RGB_Image*img=newFl_RGB_Image(pdata,175,126);
  12. btn->image(img);
  13. }
  14. win->end();
  15. win->show(argc,argv);
  16. return(Fl::run());
  17. }
int main(int argc, char *argv[]) 
{
	size_t sz = 175*126*3;
	unsigned char *pdata = new unsigned char[sz];
	size_t len = load_imgdata("test.dat", pdata, sz);

	printf("len =%u\n", len);

	Fl::scheme("GTK+");
	Fl_Window *win = new Fl_Window(800,400,"Tabs Example");
	{		
 		Fl_Button *btn = new Fl_Button(120, 140, 200, 200, "button");
		Fl_RGB_Image *img = new Fl_RGB_Image(pdata, 175, 126);
		btn->image(img);
	}
	win->end();
	win->show(argc, argv);
	return(Fl::run());
}


显示结果如下:


图像数据是自己随便写入的,所以不是什么规则的图像,但是显示是没有问题的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值