예제 #1
0
static std::pair<bool, String> save_png_gdiplus(const Path &filename, const ImageRGB &img)
{
	// gdi+ does not support URIs
	Path winname(filename);
	winname.ToWindows();
	const auto newsize = winname.Size() + 1;
	auto wcstring = std::vector<wchar_t>(newsize);
	auto convertedChars = size_t(0);
	mbstowcs_s(&convertedChars, wcstring.data(), newsize, winname.CStr(), _TRUNCATE);

	Gdiplus::Bitmap *outbm = new Gdiplus::Bitmap(INT(img.GetWidth()), INT(img.GetHeight()), PixelFormat24bppRGB);
	if (!outbm)
	{
		return std::make_pair(false, String(_("Cannot create bitmap")));
	}
	Gdiplus::BitmapData bitmapData;
	auto clip = Gdiplus::Rect(0, 0, outbm->GetWidth(), outbm->GetHeight());
	outbm->LockBits(&clip, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);
	auto *pixels = (uint8_t*)bitmapData.Scan0;
//#pragma omp parallel for
	FOREACHPIXEL(x, y, img)
	{
		size_t poffset = 3 * x + y * bitmapData.Stride;
		const auto &pix = img.At(x, y);
		pixels[poffset + 2] = pix.r;
		pixels[poffset + 1] = pix.g;
		pixels[poffset] = pix.b;
	}
예제 #2
0
static std::pair<bool, String> save_png_gdkpixbuf(const Path &fname, const ImageRGB &img)
{
	GdkPixbuf *pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 
			int(img.GetWidth()), int(img.GetHeight()));
	if (!pb)
	{
		return std::make_pair(false, String(_("Cannot create temporary buffer.")));
	}

	int w = gdk_pixbuf_get_width(pb);
	int h = gdk_pixbuf_get_height(pb);
	int rs = gdk_pixbuf_get_rowstride(pb);
	guchar *ppix = gdk_pixbuf_get_pixels(pb);
	for (int y = 0; y < h; y++)
		for (int x = 0; x < w; x++)
		{
			const auto px = img.At(x, y);
			int o2 = x + x + x + y * rs;
			ppix[o2] = px.r;
			ppix[o2 + 1] = px.g;
			ppix[o2 + 2] = px.b;
		}

	GError *err = NULL;
	gchar *utfname;
	gsize i;
	utfname = g_locale_to_utf8(fname.CStr(), -1, NULL, &i, NULL);
	gchar *filename;
	filename = g_filename_from_utf8(utfname, -1, NULL, &i, NULL);
	g_free(utfname);
	gchar *tinfo = g_locale_to_utf8("tEXt::Source", -1, NULL, &i, NULL);
	gchar *tinfo2 = g_locale_to_utf8("Saved by libcrn.", -1, NULL, &i, NULL);
	bool ok = gdk_pixbuf_save(pb, filename, "png", &err, tinfo, tinfo2, NULL); 
	g_free(filename);
	g_free(tinfo);
	g_free(tinfo2);
	g_object_unref(pb);
	String out(U"");
	if (!ok)
	{
		out = String(_("Cannot save file. ")) + err->message;
		g_error_free(err);
	}
	return std::make_pair(ok, out);
}
예제 #3
0
static std::pair<bool, String> save_png_libpng(const Path &filename, const ImageRGB &img)
{
	// libpng does not support URIs
	Path fname(filename);
	fname.ToLocal();

	std::unique_ptr<FILE, decltype(fclose_if_not_null)*> fp(fopen(fname.CStr(), "wb"), fclose_if_not_null);
	if (!fp)
	{
		return std::make_pair(false, String(_("Cannot create file ")) + U"<" + fname + U">");
	}

	/* Create png struct & info */
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr)
	{
		return std::make_pair(false, String(_("Cannot create the PNG structure.")));
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		return std::make_pair(false, String(_("Cannot create the PNG info.")));
	}

	/* Set up the error handling */
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return std::make_pair(false, String(_("Error while generating the PNG image.")));
	}

	/* setup libpng for using standard C fwrite() function with our FILE pointer */
	png_init_io(png_ptr, fp.get());

	/* Fill in the png_info structure */
	int width = int(img.GetWidth());
	int height = int(img.GetHeight());
	int bit_depth = 8;
	int color_type = PNG_COLOR_TYPE_RGB;
	int interlace_type = PNG_INTERLACE_NONE;
	int compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
	int filter_method = PNG_FILTER_TYPE_DEFAULT;
	png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_method);

	/* Using the low-level write interface */
	png_write_info(png_ptr, info_ptr);
	png_bytepp row_pointers;
	row_pointers = (png_bytep*)malloc(sizeof(png_byte*) * height);
	for (int i = 0; i < height ; ++i)
	{
#if (PNG_LIBPNG_VER > 10300)
		row_pointers[i] = (png_bytep)calloc(1, png_get_rowbytes(png_ptr, info_ptr));
#else
		row_pointers[i] = (png_bytep)calloc(1, info_ptr->rowbytes);
#endif
	}

	/* Conversion */
#if (PNG_LIBPNG_VER > 10300)
	int channels = png_get_channels(png_ptr, info_ptr);
#else
	int channels = info_ptr->channels;
#endif
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			const auto px = img.At(x, y);
			row_pointers[y][x * channels] = px.r;
			row_pointers[y][x * channels + 1] = px.g;
			row_pointers[y][x * channels + 2] = px.b;
		}

	png_write_image(png_ptr, row_pointers);

	// TODO more options
	png_text txt[1];
	txt[0].compression = PNG_TEXT_COMPRESSION_NONE;
	txt[0].key = (char*)"creator";
	txt[0].text = (char*)"libcrn";
	txt[0].text_length = strlen(txt[0].text);
	png_set_text(png_ptr, info_ptr, txt, 1);

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	// free
	for (int i = 0; i < height ; ++i)
	{
		free(row_pointers[i]);
	}
	free(row_pointers);
	return std::make_pair(true, String(""));

}