环境:ubuntu12.10
这几天需要在ubuntu12.10下实现截取桌面图像并保存为png格式的文件,期间截屏的代码借鉴了http://bbs.csdn.net/topics/340056849处提供的方法。
保存为png借鉴了CxImage里面保存png的代码,经过大半天的测试,算是搞定了截屏保存为png格式的需求。
1、截屏的代码
int captureDesktop(const
char* filename)
{
Window desktop;
Display* dap = NULL;
XImage* img = NULL;
int screen_width = 0;
int screen_height = 0;
dsp = XOpenDisplay(NULL);/* Connect to a local display */
if(NULL==dsp)
{
return 0;
}
desktop = RootWindow(dsp,0);/* Refer to the root window */
if(0==desktop)
{
return 0;
}
/*
Retrive the width and the height of the screen */
screen_width = DisplayWidth(dsp,0);
screen_height = DisplayHeight(dsp,0);
/* Get the Image of the root window */
img = XGetImage(dsp,desktop,0,0,screen_width,screen_height,~0,ZPixmap);
if(img != NULL){
write_png(filename,img);
XDestroyImage(img);
}
XCloseDisplay(dsp);
return 1;
}
2、保存为png文件
/* Write a png file */
int write_png(const
char *file_name ,XImage*image)
{
png_struct *png_ptr = NULL;
png_info *info_ptr = NULL;
FILE*fp =
fopen(file_name,"wb+");
/* 分配并初始化png_struct数据结构(必须) */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,(void
*)NULL,NULL,NULL);
if (png_ptr == NULL)
return -1;
/* 分配并初始化png_info数据结构(必须) */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL){
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return -1;
}
/* 设置输出控制 */
png_init_io(png_ptr, fp);
/* 设置文件信息 */
info_ptr->width = image->width;
info_ptr->height = image->height;
info_ptr->pixel_depth = (unsigned
char)image->depth;
info_ptr->channels = (image->bits_per_pixel>8) ? (unsigned
char)3: (unsigned
char)1;
info_ptr->bit_depth = (unsigned
char)(image->depth/info_ptr->channels);
info_ptr->compression_type = 0;
info_ptr->filter_type = 0;
info_ptr->valid = 0;
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
info_ptr->channels++;
info_ptr->bit_depth = 8;
info_ptr->pixel_depth += 8;
info_ptr->interlace_type = PNG_INTERLACE_NONE;
/* 设置最好压缩比 */
int compress_level = Z_BEST_COMPRESSION;
png_set_compression_level(png_ptr, compress_level);
//关键参数:WINDOWS上截图通常只有RGB,UBUNTU截图是RGBA,否则出来的图像显示不正传
info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
/* 设置背景 */
png_color_16 image_background={ 0, 255, 255, 255, 0 };
png_set_bKGD(png_ptr, info_ptr, &image_background);
/* 设置尺寸 metrics */
png_set_IHDR(png_ptr, info_ptr, info_ptr->width, info_ptr->height,
info_ptr->bit_depth,
info_ptr->color_type, info_ptr->interlace_type,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
int row_size = image->bytes_per_line;
info_ptr->rowbytes = row_size;
unsigned
char *row_pointers =
new unsigned
char[row_size];
/* 写文件信息 */
png_write_info(png_ptr, info_ptr);
//interlace handling
int num_pass = png_set_interlace_handling(png_ptr);
for (int pass = 0; pass < num_pass; pass++){
//写图像
int ay=0;
do
{
memcpy(row_pointers,image->data+ay*4*image->width,row_size);
RGBtoBGR(row_pointers, row_size);
png_write_row(png_ptr, row_pointers);
ay++;
} while(ay<=(image->height-1));
}
// 释放临时分配的内存
delete [] row_pointers;
row_pointers = NULL;
/* 写文件尾 (必须调用)*/
png_write_end(png_ptr, info_ptr);
/* 清除并释放分配的内存 */
png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr);
/* 关闭文件 */
if(fp != NULL){
fclose(fp);
fp = NULL;
}
return 0;
}
3、
/**
* 交换RGB图像的蓝 {MOD}和红 {MOD}分量
* 参数buffer : pointer to the pixels
* 参数length : number of bytes to swap. lenght may not exceed the scan line.
*/
void RGBtoBGR(unsigned char *buffer, int length)
{
if (buffer != NULL){
unsigned char temp;
//通常UBUNTU截图是4个字节表示一个像素(RGB+A)
for (int i=0;i
temp = buffer[i];
buffer[i] = buffer[i+2];
buffer[i+2] = temp;
}
}
}