| 472 | } |
| 473 | |
| 474 | void Image::writePng(IODevicePtr device) const { |
| 475 | auto writePngData = [](png_structp pngPtr, png_bytep data, png_size_t length) { |
| 476 | IODevice* device = (IODevice*)png_get_io_ptr(pngPtr); |
| 477 | device->writeFull((char*)data, length); |
| 478 | }; |
| 479 | |
| 480 | auto flushPngData = [](png_structp) {}; |
| 481 | |
| 482 | png_structp png_ptr = nullptr; |
| 483 | png_infop info_ptr = nullptr; |
| 484 | |
| 485 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |
| 486 | if (!png_ptr) |
| 487 | throw ImageException("Internal libPNG error"); |
| 488 | |
| 489 | info_ptr = png_create_info_struct(png_ptr); |
| 490 | if (!info_ptr) { |
| 491 | png_destroy_write_struct(&png_ptr, nullptr); |
| 492 | throw ImageException("Internal libPNG error"); |
| 493 | } |
| 494 | |
| 495 | if (setjmp(png_jmpbuf(png_ptr))) { |
| 496 | png_destroy_write_struct(&png_ptr, &info_ptr); |
| 497 | throw ImageException("Internal error reading png."); |
| 498 | } |
| 499 | |
| 500 | unsigned channels = m_pixelFormat == PixelFormat::RGB24 ? 3 : 4; |
| 501 | |
| 502 | png_set_IHDR(png_ptr, |
| 503 | info_ptr, |
| 504 | m_width, |
| 505 | m_height, |
| 506 | 8, |
| 507 | channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, |
| 508 | PNG_INTERLACE_NONE, |
| 509 | PNG_COMPRESSION_TYPE_DEFAULT, |
| 510 | PNG_FILTER_TYPE_DEFAULT); |
| 511 | |
| 512 | unique_ptr<png_bytep[]> row_ptrs(new png_bytep[m_height]); |
| 513 | size_t stride = m_width * 8 * channels / 8; |
| 514 | for (size_t i = 0; i < m_height; ++i) { |
| 515 | size_t q = (m_height - i - 1) * stride; |
| 516 | row_ptrs[i] = (png_bytep)m_data + q; |
| 517 | } |
| 518 | |
| 519 | png_set_write_fn(png_ptr, device.get(), writePngData, flushPngData); |
| 520 | png_set_rows(png_ptr, info_ptr, row_ptrs.get()); |
| 521 | png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); |
| 522 | |
| 523 | png_destroy_write_struct(&png_ptr, &info_ptr); |
| 524 | } |
| 525 | |
| 526 | ImageView::ImageView(Image const& image) { |
| 527 | size = image.size(); |
no test coverage detected