Go to the documentation of this file.00001 #include "cartographer/io/image.h"
00002
00003 #include <memory>
00004
00005 #include "cartographer/io/file_writer.h"
00006 #include "glog/logging.h"
00007
00008 namespace cartographer {
00009 namespace io {
00010 namespace {
00011
00012 uint32 Uint8ColorToCairo(const Uint8Color& color) {
00013 return static_cast<uint32>(255) << 24 | static_cast<uint32>(color[0]) << 16 |
00014 static_cast<uint32>(color[1]) << 8 | color[2];
00015 }
00016
00017 Uint8Color CairoToUint8Color(uint32 color) {
00018 uint8 r = color >> 16;
00019 uint8 g = color >> 8;
00020 uint8 b = color;
00021 return {{r, g, b}};
00022 }
00023
00024 cairo_status_t CairoWriteCallback(void* const closure,
00025 const unsigned char* data,
00026 const unsigned int length) {
00027 if (static_cast<FileWriter*>(closure)->Write(
00028 reinterpret_cast<const char*>(data), length)) {
00029 return CAIRO_STATUS_SUCCESS;
00030 }
00031 return CAIRO_STATUS_WRITE_ERROR;
00032 }
00033
00034 void CheckStrideIsAsExpected(int width) {
00035 const int stride = cairo_format_stride_for_width(kCairoFormat, width);
00036 CHECK_EQ(stride, width * 4);
00037 }
00038
00039 }
00040
00041 UniqueCairoSurfacePtr MakeUniqueCairoSurfacePtr(cairo_surface_t* surface) {
00042 return UniqueCairoSurfacePtr(surface, cairo_surface_destroy);
00043 }
00044
00045 UniqueCairoPtr MakeUniqueCairoPtr(cairo_t* surface) {
00046 return UniqueCairoPtr(surface, cairo_destroy);
00047 }
00048
00049 Image::Image(int width, int height)
00050 : width_(width), height_(height), pixels_(width * height, 0) {}
00051
00052 Image::Image(UniqueCairoSurfacePtr surface)
00053 : width_(cairo_image_surface_get_width(surface.get())),
00054 height_(cairo_image_surface_get_height(surface.get())) {
00055 CHECK_EQ(cairo_image_surface_get_format(surface.get()), kCairoFormat);
00056 CheckStrideIsAsExpected(width_);
00057
00058 const uint32* pixel_data =
00059 reinterpret_cast<uint32*>(cairo_image_surface_get_data(surface.get()));
00060 const int num_pixels = width_ * height_;
00061 pixels_.reserve(num_pixels);
00062 for (int i = 0; i < num_pixels; ++i) {
00063 pixels_.push_back(pixel_data[i]);
00064 }
00065 }
00066
00067 void Image::Rotate90DegreesClockwise() {
00068 const auto old_pixels = pixels_;
00069 pixels_.clear();
00070 for (int x = 0; x < width_; ++x) {
00071 for (int y = height_ - 1; y >= 0; --y) {
00072 pixels_.push_back(old_pixels.at(y * width_ + x));
00073 }
00074 }
00075 std::swap(width_, height_);
00076 }
00077
00078 void Image::WritePng(FileWriter* const file_writer) {
00079
00080
00081
00082
00083
00084 UniqueCairoSurfacePtr surface = GetCairoSurface();
00085 CHECK_EQ(cairo_surface_status(surface.get()), CAIRO_STATUS_SUCCESS);
00086 CHECK_EQ(cairo_surface_write_to_png_stream(surface.get(), &CairoWriteCallback,
00087 file_writer),
00088 CAIRO_STATUS_SUCCESS);
00089 }
00090
00091 const Uint8Color Image::GetPixel(int x, int y) const {
00092 return CairoToUint8Color(pixels_[y * width_ + x]);
00093 }
00094
00095 void Image::SetPixel(int x, int y, const Uint8Color& color) {
00096 pixels_[y * width_ + x] = Uint8ColorToCairo(color);
00097 }
00098
00099 UniqueCairoSurfacePtr Image::GetCairoSurface() {
00100 return MakeUniqueCairoSurfacePtr(cairo_image_surface_create_for_data(
00101 reinterpret_cast<unsigned char*>(pixels_.data()), kCairoFormat, width_,
00102 height_, width_ * 4 ));
00103 }
00104
00105 }
00106 }