blob: 5a7500ea662d535ddd131670ec7f4d81226521b3 [file] [log] [blame]
// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdio>
#include <sstream>
#include <cairo/cairo.h>
#include <gflags/gflags.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "base/logging.h"
DEFINE_string(window, "",
"Window to capture, as a hexadecimal X ID "
"(if empty, the root window is captured)");
using std::hex;
using std::istringstream;
static const char* kUsage =
"Usage: screenshot [FLAGS] FILENAME.png\n"
"\n"
"Saves the contents of the entire screen or of a window to a file.";
int main(int argc, char** argv) {
google::SetUsageMessage(kUsage);
google::ParseCommandLineFlags(&argc, &argv, true);
if (argc != 2) {
google::ShowUsageWithFlags(argv[0]);
return 1;
}
Display* display = XOpenDisplay(NULL);
CHECK(display);
const char* filename = argv[1];
Window win = None;
if (FLAGS_window.empty()) {
win = DefaultRootWindow(display);
} else {
istringstream input(FLAGS_window);
CHECK(!(input >> hex >> win).fail())
<< "Unable to parse \"" << input << "\" as window "
<< "(should be hexadecimal X ID)";
}
Window root = None;
int x = 0, y = 0;
unsigned int width = 0, height = 0, border_width = 0, depth = 0;
CHECK(XGetGeometry(display, win, &root, &x, &y, &width, &height,
&border_width, &depth));
XImage* image = XGetImage(
display, win, 0, 0, width, height, AllPlanes, ZPixmap);
CHECK(image);
CHECK(image->depth == 24 || image->depth == 32)
<< "Unsupported image depth " << image->depth;
cairo_surface_t* surface =
cairo_image_surface_create_for_data(
reinterpret_cast<unsigned char*>(image->data),
image->depth == 24 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32,
image->width,
image->height,
image->bytes_per_line);
CHECK(surface) << "Unable to create Cairo surface from XImage data";
CHECK(cairo_surface_write_to_png(surface, filename) == CAIRO_STATUS_SUCCESS);
cairo_surface_destroy(surface);
XDestroyImage(image);
XCloseDisplay(display);
return 0;
}