[cairo] Writing Surface to PNG based on Window Context: POSSIBLE?
darethehair
darethehair at gmail.com
Sat Mar 21 06:20:20 PDT 2009
Gerdus van Zyl wrote:
> Well it works for me! Below is the code I use:
> tsurf = ctx.get_target()
> tsurf.write_to_png("screenshot.png")
>
> This is code that works on MS Windows. According to the API docs it
> should work for any pixel based surface. But as suggested if you
> structure your code to be able to render to any cairo context that
> would of course be better in the long term.
>
> ~Gerdus
>
> On Sat, Mar 21, 2009 at 3:22 AM, Neil Mayhew
> <neil_mayhew at users.sourceforge.net> wrote:
>
>> On 20/03/09 04:31 PM darethehair wrote:
>>
>>> How does one invoke the 'write_to_png' in that situation? The reason I
>>> ask this is that I would like to be able to draw on the 'screen', but
>>> also re-direct to a PNG (or whatever) file if I want to.
>>>
>> You can't write a window to a PNG (not with cairo, anyway). However, you
>> can refactor your program into two parts: one that takes a cairo.Context
>> as a parameter and generates the desired graphics, and another one that
>> sets up the destination surface and context and calls the other
>> (drawing) part.
>>
>> I've done this for one program I have been writing. It uses gtkmm and
>> cairomm rather than PyCairo, but the principle is the same. Depending on
>> the command-line arguments it either opens up a window and hooks the
>> pure-cairo drawing function to the expose event, or it creates a
>> pure-cairo surface, calls the drawing function on that, and then writes
>> it out. However, you could instead have a File -> Export menu item that
>> does the same thing.
>>
>> In case it's helpful, I've included the code I am using. It's in C++,
>> but hopefully you can translate.
>>
>> --Neil
>>
>> void export(std::string filename, int size_x, int size_y)
>> {
>> std::string suffix = filename.substr(filename.rfind('.') + 1);
>>
>> Cairo::RefPtr<Cairo::Surface> surface;
>>
>> if (suffix == "pdf")
>> surface = Cairo::PdfSurface::create(filename, size_x, size_y);
>> else if (suffix == "svg")
>> surface = Cairo::SvgSurface::create(filename, size_x, size_y);
>> else if (suffix == "ps")
>> surface = Cairo::PsSurface::create(filename, size_x, size_y);
>> else if (suffix == "png")
>> surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, \
>> size_x, size_y);
>> else
>> throw std::runtime_error("Unknown filename suffix");
>>
>> Cairo::RefPtr<Cairo::Context> context = \
>> Cairo::Context::create(surface);
>>
>> if (suffix == "png")
>> {
>> context->set_source_rgb(1.0, 1.0, 1.0);
>> context->paint();
>> }
>>
>> render(context, size_x, size_y);
>>
>> if (suffix == "png")
>> surface->write_to_png(filename);
>> }
>>
>> _______________________________________________
>> cairo mailing list
>> cairo at cairographics.org
>> http://lists.cairographics.org/mailman/listinfo/cairo
>>
>>
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo
>
Thanks to you both!
I pondered what Neil had said, and agreed that pushing *two* contexts --
one window-based, and another PNG-based -- through the same 'drawing'
code -- would accomplish what I had desired. However, I couldn't help
thinking that there must be some better/easier way of somehow
transferring one to another, without the hassle of repeating the same
drawing code all over again. It looks like Gerdus has the solution I
was looking for!
Again, I am a total newbie, but this sounds like a perfect
question/answer in an FAQ somewhere, right?
Dare
More information about the cairo
mailing list