Cleanup and new features in Image code. (#685)
- Removes stride_, since we know for a fact that it is always width * 4. - Adds a constructor from a cairo surface. - Adds a function that rotates the image by 90 degrees. This is in preparation of adding a tool that can generate an image from a .pbstream.master
parent
0b4e7a9443
commit
5ee830e8cc
|
@ -31,10 +31,9 @@ cairo_status_t CairoWriteCallback(void* const closure,
|
||||||
return CAIRO_STATUS_WRITE_ERROR;
|
return CAIRO_STATUS_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StrideForWidth(int width) {
|
void CheckStrideIsAsExpected(int width) {
|
||||||
const int stride = cairo_format_stride_for_width(kCairoFormat, width);
|
const int stride = cairo_format_stride_for_width(kCairoFormat, width);
|
||||||
CHECK_EQ(stride % 4, 0);
|
CHECK_EQ(stride, width * 4);
|
||||||
return stride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -48,10 +47,33 @@ UniqueCairoPtr MakeUniqueCairoPtr(cairo_t* surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(int width, int height)
|
Image::Image(int width, int height)
|
||||||
: width_(width),
|
: width_(width), height_(height), pixels_(width * height, 0) {}
|
||||||
height_(height),
|
|
||||||
stride_(StrideForWidth(width)),
|
Image::Image(UniqueCairoSurfacePtr surface)
|
||||||
pixels_(stride_ / 4 * height, 0) {}
|
: width_(cairo_image_surface_get_width(surface.get())),
|
||||||
|
height_(cairo_image_surface_get_height(surface.get())) {
|
||||||
|
CHECK_EQ(cairo_image_surface_get_format(surface.get()), kCairoFormat);
|
||||||
|
CheckStrideIsAsExpected(width_);
|
||||||
|
|
||||||
|
const uint32* pixel_data =
|
||||||
|
reinterpret_cast<uint32*>(cairo_image_surface_get_data(surface.get()));
|
||||||
|
const int num_pixels = width_ * height_;
|
||||||
|
pixels_.reserve(num_pixels);
|
||||||
|
for (int i = 0; i < num_pixels; ++i) {
|
||||||
|
pixels_.push_back(pixel_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::Rotate90DegreesClockwise() {
|
||||||
|
const auto old_pixels = pixels_;
|
||||||
|
pixels_.clear();
|
||||||
|
for (int x = 0; x < width_; ++x) {
|
||||||
|
for (int y = height_ - 1; y >= 0; --y) {
|
||||||
|
pixels_.push_back(old_pixels.at(y * width_ + x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::swap(width_, height_);
|
||||||
|
}
|
||||||
|
|
||||||
void Image::WritePng(FileWriter* const file_writer) {
|
void Image::WritePng(FileWriter* const file_writer) {
|
||||||
// TODO(hrapp): cairo_image_surface_create_for_data does not take ownership of
|
// TODO(hrapp): cairo_image_surface_create_for_data does not take ownership of
|
||||||
|
@ -67,17 +89,17 @@ void Image::WritePng(FileWriter* const file_writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Uint8Color Image::GetPixel(int x, int y) const {
|
const Uint8Color Image::GetPixel(int x, int y) const {
|
||||||
return CairoToUint8Color(pixels_[y * stride_ / 4 + x]);
|
return CairoToUint8Color(pixels_[y * width_ + x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::SetPixel(int x, int y, const Uint8Color& color) {
|
void Image::SetPixel(int x, int y, const Uint8Color& color) {
|
||||||
pixels_[y * stride_ / 4 + x] = Uint8ColorToCairo(color);
|
pixels_[y * width_ + x] = Uint8ColorToCairo(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueCairoSurfacePtr Image::GetCairoSurface() {
|
UniqueCairoSurfacePtr Image::GetCairoSurface() {
|
||||||
return MakeUniqueCairoSurfacePtr(cairo_image_surface_create_for_data(
|
return MakeUniqueCairoSurfacePtr(cairo_image_surface_create_for_data(
|
||||||
reinterpret_cast<unsigned char*>(pixels_.data()), kCairoFormat, width_,
|
reinterpret_cast<unsigned char*>(pixels_.data()), kCairoFormat, width_,
|
||||||
height_, stride_));
|
height_, width_ * 4 /* stride */));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace io
|
} // namespace io
|
||||||
|
|
|
@ -48,12 +48,16 @@ UniqueCairoPtr MakeUniqueCairoPtr(cairo_t* surface);
|
||||||
|
|
||||||
class Image {
|
class Image {
|
||||||
public:
|
public:
|
||||||
|
explicit Image(UniqueCairoSurfacePtr surface);
|
||||||
Image(int width, int height);
|
Image(int width, int height);
|
||||||
|
|
||||||
const Uint8Color GetPixel(int x, int y) const;
|
const Uint8Color GetPixel(int x, int y) const;
|
||||||
void SetPixel(int x, int y, const Uint8Color& color);
|
void SetPixel(int x, int y, const Uint8Color& color);
|
||||||
void WritePng(FileWriter* const file_writer);
|
void WritePng(FileWriter* const file_writer);
|
||||||
|
|
||||||
|
// Rotates the image in place.
|
||||||
|
void Rotate90DegreesClockwise();
|
||||||
|
|
||||||
// Returns a pointer to a cairo surface that contains the current pixel data.
|
// Returns a pointer to a cairo surface that contains the current pixel data.
|
||||||
// The 'Image' object must therefore outlive the returned surface object. It
|
// The 'Image' object must therefore outlive the returned surface object. It
|
||||||
// is undefined behavior to call any of the mutating functions while a pointer
|
// is undefined behavior to call any of the mutating functions while a pointer
|
||||||
|
@ -66,7 +70,6 @@ class Image {
|
||||||
private:
|
private:
|
||||||
int width_;
|
int width_;
|
||||||
int height_;
|
int height_;
|
||||||
int stride_;
|
|
||||||
std::vector<uint32> pixels_;
|
std::vector<uint32> pixels_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue