Containers::Array<char> StbPngImageConverter::doExportToData(const ImageView2D& image) { #ifndef MAGNUM_TARGET_GLES if(image.storage().swapBytes()) { Error() << "Trade::StbPngImageConverter::exportToData(): pixel byte swap is not supported"; return nullptr; } #endif if(image.type() != PixelType::UnsignedByte) { Error() << "Trade::StbPngImageConverter::exportToData(): unsupported pixel type" << image.type(); return nullptr; } Int components; switch(image.format()) { #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) case PixelFormat::Red: #endif #ifdef MAGNUM_TARGET_GLES2 case PixelFormat::Luminance: #endif components = 1; break; #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) case PixelFormat::RG: #endif #ifdef MAGNUM_TARGET_GLES2 case PixelFormat::LuminanceAlpha: #endif components = 2; break; case PixelFormat::RGB: components = 3; break; case PixelFormat::RGBA: components = 4; break; default: Error() << "Trade::StbPngImageConverter::exportToData(): unsupported pixel format" << image.format(); return nullptr; } /* Data properties */ std::size_t offset; Math::Vector2<std::size_t> dataSize; std::tie(offset, dataSize, std::ignore) = image.dataProperties(); /* Reverse rows in image data */ Containers::Array<unsigned char> reversedData{image.data().size()}; for(Int y = 0; y != image.size().y(); ++y) { std::copy(image.data<unsigned char>() + offset + y*dataSize.x(), image.data<unsigned char>() + offset + (y + 1)*dataSize.x(), reversedData + (image.size().y() - y - 1)*dataSize.x()); } Int size; unsigned char* const data = stbi_write_png_to_mem(reversedData, dataSize.x(), image.size().x(), image.size().y(), components, &size); CORRADE_INTERNAL_ASSERT(data); /* Wrap the data in an array with custom deleter (we can't use delete[]) */ Containers::Array<char> fileData{reinterpret_cast<char*>(data), std::size_t(size), [](char* data, std::size_t) { std::free(data); }}; return fileData; }
Containers::Array<char> TgaImageConverter::doExportToData(const ImageView2D& image) { #ifndef MAGNUM_TARGET_GLES if(image.storage().swapBytes()) { Error() << "Trade::TgaImageConverter::exportToData(): pixel byte swap is not supported"; return nullptr; } #endif if(image.format() != PixelFormat::RGB && image.format() != PixelFormat::RGBA #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) && image.format() != PixelFormat::Red #endif #ifdef MAGNUM_TARGET_GLES2 && image.format() != PixelFormat::Luminance #endif ) { Error() << "Trade::TgaImageConverter::exportToData(): unsupported color format" << image.format(); return nullptr; } if(image.type() != PixelType::UnsignedByte) { Error() << "Trade::TgaImageConverter::exportToData(): unsupported color type" << image.type(); return nullptr; } /* Initialize data buffer */ const auto pixelSize = UnsignedByte(image.pixelSize()); Containers::Array<char> data{Containers::ValueInit, sizeof(TgaHeader) + pixelSize*image.size().product()}; /* Fill header */ auto header = reinterpret_cast<TgaHeader*>(data.begin()); switch(image.format()) { case PixelFormat::RGB: case PixelFormat::RGBA: header->imageType = 2; break; #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) case PixelFormat::Red: #endif #ifdef MAGNUM_TARGET_GLES2 case PixelFormat::Luminance: #endif header->imageType = 3; break; default: CORRADE_ASSERT_UNREACHABLE(); } header->bpp = pixelSize*8; header->width = UnsignedShort(Utility::Endianness::littleEndian(image.size().x())); header->height = UnsignedShort(Utility::Endianness::littleEndian(image.size().y())); /* Image data pointer including skip */ const char* imageData = image.data() + std::get<0>(image.dataProperties()); /* Fill data or copy them row by row if we need to drop the padding */ const std::size_t rowSize = image.size().x()*pixelSize; const std::size_t rowStride = std::get<1>(image.dataProperties()).x(); if(rowStride != rowSize) { for(std::int_fast32_t y = 0; y != image.size().y(); ++y) std::copy_n(imageData + y*rowStride, rowSize, data.begin() + sizeof(TgaHeader) + y*rowSize); } else std::copy_n(imageData, pixelSize*image.size().product(), data.begin() + sizeof(TgaHeader)); if(image.format() == PixelFormat::RGB) { auto pixels = reinterpret_cast<Math::Vector3<UnsignedByte>*>(data.begin()+sizeof(TgaHeader)); std::transform(pixels, pixels + image.size().product(), pixels, [](Math::Vector3<UnsignedByte> pixel) { return Math::swizzle<'b', 'g', 'r'>(pixel); }); } else if(image.format() == PixelFormat::RGBA) { auto pixels = reinterpret_cast<Math::Vector4<UnsignedByte>*>(data.begin()+sizeof(TgaHeader)); std::transform(pixels, pixels + image.size().product(), pixels, [](Math::Vector4<UnsignedByte> pixel) { return Math::swizzle<'b', 'g', 'r', 'a'>(pixel); }); } return data; }
Containers::Array<char> doExportToData(const ImageView2D& image) override { return Containers::Array<char>::from(char(image.size().x()), char(image.size().y())); };