void Gosu::saveImageFile(const Gosu::Bitmap& bitmap, Gosu::Writer writer, const std::wstring& formatHint) { unsigned char* rgba = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(bitmap.data())); // TODO: Use the new *_to_func functions in stb_imagewrite.h instead: // https://github.com/nothings/stb/blob/master/stb_image_write.h#L39 int length; unsigned char* png = stbi_write_png_to_mem(rgba, 0, bitmap.width(), bitmap.height(), 4, &length); if (png == 0) throw std::runtime_error("Could not save image data to memory"); try { writer.write(png, length); } catch (...) { STBIW_FREE(png); throw; } STBIW_FREE(png); }
void Gosu::saveImageFile(const Gosu::Bitmap& bitmap, Gosu::Writer writer, const std::wstring& formatHint) { unsigned char* rgba = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(bitmap.data())); int length; unsigned char* png = stbi_write_png_to_mem(rgba, 0, bitmap.width(), bitmap.height(), 4, &length); if (png == 0) throw std::runtime_error("Could not save image data to memory"); try { writer.write(png, length); } catch (...) { STBIW_FREE(png); throw; } STBIW_FREE(png); }
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; }
static void ugtk_openavatarthread(void *UNUSED(args)) { void *dialog = utoxGTK_file_chooser_dialog_new((const char *)S(SELECT_AVATAR_TITLE), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL, "_Open", GTK_RESPONSE_ACCEPT, NULL); void *filter = utoxGTK_file_filter_new(); utoxGTK_file_filter_add_mime_type(filter, "image/jpeg"); utoxGTK_file_filter_add_mime_type(filter, "image/png"); utoxGTK_file_filter_add_mime_type(filter, "image/bmp"); utoxGTK_file_filter_add_mime_type(filter, "image/gif"); utoxGTK_file_chooser_set_filter(dialog, filter); void *preview = utoxGTK_image_new(); utoxGTK_file_chooser_set_preview_widget(dialog, preview); utoxGTK_signal_connect_data(dialog, "update-preview", update_image_preview, preview, NULL, 0); while (utoxGTK_dialog_run(dialog) == GTK_RESPONSE_ACCEPT) { char *filename = utoxGTK_file_chooser_get_filename(dialog); int size; int width, height, bpp; uint8_t *img = stbi_load(filename, &width, &height, &bpp, 0); uint8_t *file_data = stbi_write_png_to_mem(img, 0, width, height, bpp, &size); free(img); utoxGTK_free(filename); if (!file_data) { void *message_dialog = utoxGTK_message_dialog_new(dialog, 0, 1, 2, (const char *)S(CANT_FIND_FILE_OR_EMPTY)); utoxGTK_dialog_run(message_dialog); utoxGTK_widget_destroy(message_dialog); } else if (size > UTOX_AVATAR_MAX_DATA_LENGTH) { free(file_data); char size_str[16]; int len = sprint_humanread_bytes(size_str, sizeof(size_str), UTOX_AVATAR_MAX_DATA_LENGTH); char err_str[265] = { 0 }; snprintf((char *)err_str, 265, "%s%.*s (%ikb loaded)", S(AVATAR_TOO_LARGE_MAX_SIZE_IS), len, size_str, (size / 1024)); void *message_dialog = utoxGTK_message_dialog_new(dialog, 0, 1, 2, err_str); utoxGTK_dialog_run(message_dialog); utoxGTK_widget_destroy(message_dialog); } else { postmessage_utox(SELF_AVATAR_SET, size, 0, file_data); break; } } utoxGTK_widget_destroy(dialog); while (utoxGTK_events_pending()) { utoxGTK_main_iteration(); } utoxGTK_open = false; }
//--------------------------------------------------------------------- DataStreamPtr STBIImageCodec::encode(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const { if(mType != "png") { OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "currently only encoding to PNG supported", "STBIImageCodec::encode" ) ; } ImageData* pImgData = static_cast<ImageData*>(pData.getPointer()); int channels = PixelUtil::getComponentCount(pImgData->format); int len; uchar *data = stbi_write_png_to_mem(input->getPtr(), pImgData->width*channels, pImgData->width, pImgData->height, channels, &len); if (!data) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error encoding image: " + String(stbi_failure_reason()), "STBIImageCodec::encode"); } return DataStreamPtr(new MemoryDataStream(data, len, true)); }
Containers::Array<char> StbPngImageConverter::doExportToData(const ImageReference2D& image) const { if(image.type() != ColorType::UnsignedByte) { Error() << "Trade::StbPngImageConverter::exportToData(): unsupported color type" << image.type(); return nullptr; } Int components; switch(image.format()) { case ColorFormat::Red: components = 1; break; case ColorFormat::RG: components = 2; break; case ColorFormat::RGB: components = 3; break; case ColorFormat::RGBA: components = 4; break; default: Error() << "Trade::StbPngImageConverter::exportToData(): unsupported color format" << image.format(); return nullptr; } /* Reverse rows in image data */ Containers::Array<unsigned char> reversedData{std::size_t(image.size().product()*components)}; for(Int y = 0; y != image.size().y(); ++y) { const Int stride = image.size().x()*components; std::copy(image.data<unsigned char>() + y*stride, image.data<unsigned char>() + (y + 1)*stride, reversedData + (image.size().y() - y - 1)*stride); } Int size; unsigned char* const data = stbi_write_png_to_mem(reversedData, 0, image.size().x(), image.size().y(), components, &size); CORRADE_INTERNAL_ASSERT(data); /* Copy the data to a new[]-allocated array so we can delete[] it later, then delete the original data with free() */ Containers::Array<char> fileData{std::size_t(size)}; std::copy(data, data + size, fileData.begin()); std::free(data); return fileData; }