Impl SaveAsPNG

This commit is contained in:
Stephen Seo 2021-11-12 13:12:15 +09:00
parent ee63cc2a7c
commit 577e7ae5e9
3 changed files with 86 additions and 1 deletions

View file

@ -60,6 +60,80 @@ unsigned int Image::GetHeight() const { return height_; }
bool Image::IsGrayscale() const { return is_grayscale_; } bool Image::IsGrayscale() const { return is_grayscale_; }
bool Image::SaveAsPNG(const std::string &filename, bool overwrite) {
if (!overwrite) {
std::ifstream ifs(filename);
if (ifs.is_open()) {
std::cout << "ERROR: File \"" << filename
<< "\" exists but overwrite == false" << std::endl;
return false;
}
}
FILE *file = std::fopen(filename.c_str(), "wb");
if (!file) {
std::cout << "ERROR: Failed to open file \"" << filename
<< "\" for writing png" << std::endl;
return false;
}
// init required structs for png encoding
png_structp png_ptr =
png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr) {
std::cout << "ERROR: Failed to initialize libpng (png_ptr) for encoding "
"PNG file \""
<< filename << '"' << std::endl;
std::fclose(file);
return false;
}
png_infop png_info_ptr = png_create_info_struct(png_ptr);
if (!png_info_ptr) {
std::cout << "ERROR: Failed to initialize libpng (png_infop) for decoding "
"PNG file \""
<< filename << '"' << std::endl;
png_destroy_write_struct(&png_ptr, nullptr);
std::fclose(file);
return false;
}
// required to handle libpng errors
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &png_info_ptr);
std::fclose(file);
return false;
}
// give FILE handle to libpng
png_init_io(png_ptr, file);
// set image information
png_set_IHDR(png_ptr, png_info_ptr, width_, height_, 8,
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// write png info
png_write_info(png_ptr, png_info_ptr);
// write rows of image data
for (unsigned int y = 0; y < height_; ++y) {
png_write_row(png_ptr, &data_.at(y * width_ * 4));
}
// finish writing image data
png_write_end(png_ptr, png_info_ptr);
// cleanup
png_destroy_write_struct(&png_ptr, &png_info_ptr);
fclose(file);
return true;
}
bool Image::SaveAsPNG(const char *filename, bool overwrite) {
return SaveAsPNG(std::string(filename), overwrite);
}
bool Image::SaveAsPPM(const std::string &filename, bool overwrite, bool Image::SaveAsPPM(const std::string &filename, bool overwrite,
bool packed) { bool packed) {
if (!IsValid()) { if (!IsValid()) {
@ -243,6 +317,7 @@ void Image::DecodePNG(const std::string &filename) {
// cleanup // cleanup
png_destroy_read_struct(&png_ptr, &png_info_ptr, &png_end_info_ptr); png_destroy_read_struct(&png_ptr, &png_info_ptr, &png_end_info_ptr);
fclose(file);
// verify // verify
if (is_grayscale_) { if (is_grayscale_) {

View file

@ -58,6 +58,16 @@ class Image {
/// Returns true if the image is grayscale. If false, then the image is RGBA. /// Returns true if the image is grayscale. If false, then the image is RGBA.
bool IsGrayscale() const; bool IsGrayscale() const;
/*!
* \brief Saves the current image data as a PNG file.
*
* Returns false if the filename already exists and overwrite is false, or if
* saving failed.
*/
bool SaveAsPNG(const std::string &filename, bool overwrite);
/// Same as SaveAsPNG()
bool SaveAsPNG(const char *filename, bool overwrite);
/*! /*!
* \brief Saves the current image data as a PPM file. * \brief Saves the current image data as a PPM file.
* *

View file

@ -3,7 +3,7 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
Image image("testin.png"); Image image("testin.png");
image.SaveAsPPM("testout.ppm", true, true); image.SaveAsPNG("testout.png", true);
return 0; return 0;
} }