Convert SVG to PDF using Python, rsvg & Cairo - cairo

I have managed to read SVG using rsvg and output it to PNG via Cairo, in Python.
Despite there being MANY similar questions, I've not seen any documentation on how to convert SVG into PDF through rsvg & cairo. I am aware of the command-line 'rsvg'/'rsvp-convert' tools, but want to incorporate the functionality into my Python code instead. No launching subprocess either.
For the sake of example, here's basically what I currently use to render PNG:
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
ctx = cairo.Context(img)
handler= rsvg.Handle(None, svgstr)
handler.render_cairo(ctx)
img.write_to_png(pngfilepath)
The question is: how would the code be changed to output PDF instead, so that vector format is kept; rasterization must not happen.

Replace your call to cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) with cairo.PDFSurface(filename, width_in_points, height_in_points). I don't know what the default scaling of the PDF surface is, but hopefully you can continue to use the same width and height values as before.
Since you explicitely mention that rasterization must now happen: Cairo "does its best" not to raster things, but there are combinations where cairo has to fall back to rasterized images. You can control the resolution of this images via the set_fallback_resolution method.
Reasons for rasterization include combinations of operations that cannot be expressed in PDF (sorry, I don't know details) and if some rasterized image is drawn to the PDF surface.

Related

Matlab plot saved as (vector) EMF but rendered as raster

I have Matlab code that produces an array of subplots that looks like this:
When I save this as an EMF file (normally a vector format) and insert in Powerpoint or view with Inkscape, then zoom in closely on the image, it looks pixelated, and clearly made up of a single encapsulated object as opposed to many small graphical objects:
This is very surprising to me, as I have for a long time been exporting Matlab plots as EMF and integrating those into Powerpoint slides, in order to build there more complex graphs that, as vector graphics, would print well at any size. These imported EMFs would also scale well and look smooth regardless of how much I zoomed into them in Powerpoint.
Can anyone guess why it is that on this occasion, this plot is not saved as a vector graphics but is instead (as it seems) rendered as raster? The code that produces this figure (based on the Matlab commands subplot, line, and scatter) is rather long/inelegant, but I can give details or simplify, if required to find a solution. Thanks!
Other similar threads on this site have not helped fix this.
I believe I have encountered this issue before. If it is the same as the issue I was facing, it is to do with the renderer being used to save the plot. Although it should automatically select the painters renderer when exporting to vector files, I have had instances where it used the openGL renderer instead, which results in bitmaps being used. I'm not entirely sure why this happens -- it might be the case that for particularly complicated figures, it reverts to openGL to avoid obnoxiously large or complicated vector files.
If you are using the print command, you can force it to use the painters algorithm as follows:
print('-painters',...)
if you're saving using File>Save As..., I believe setting the renderer for the figure should work:
set(figure_handle,'renderer','painters');
For explanation, per the MATLAB documentation:
-opengl' — OpenGL renderer. Use this renderer when saving bitmap images. OpenGL produces a bitmap image even with vector formats, which might limit the extent to which you can edit the image in other applications.
'-painters' — Painters renderer. Use this renderer when saving vector graphics files. If you save to a vector graphics file and if the figure RendererMode property is set to 'auto', then print automatically attempts to use the Painters renderer. If you want to ensure that your output format is a true vector graphics file, then specify the Painters renderer. For example:
print('-painters','-deps','myVectorFile')
If you do not specify the renderer, then print automatically uses the appropriate renderer to produce the output format requested. However, if you set the Renderer property for the figure, then print uses that renderer when generating output.
EDIT: Another option is to use the Copy Figure command (Edit > Copy Figure) -- this should copy the figure as an EMF file, and should obey the figure's renderer settings.

Using GhostScript to export PNGs at fixed size

We have many square EPS images, which we would like to export via script to PNG at very specific formats/sizes, namely
8192x8192, greyscale, no alpha, no anti-aliasing
2048x2048,greyscale, no alpha, anti-aliased.
We have had no luck scripting the "professional" tools Photoshop or Illustrator to do this (although we can do so through the UI, their weak scripting support does not give control over alpha or precise image export size, so we either always get alpha in the large images, or we sometimes get slightly inaccurate image sizes which breaks subsequent algorithms.)
Our first attempt at doing the high resolution version of this was:
gs -sDEVICE=pnggray -o cover.png -dDEVICEWIDTHPOINTS=8192 -dDEVICEHEIGHTPOINTS=8192 -dGraphicsAlphaBits=1 -dPDFFitPage=true cover.eps
However, this does not seem to resize the image to fill the box as expected.
Is there a way, given a square EPS, to get Ghostscript to do what we want?
Your problem with EPS files is that they do not request a media size. That's because EPS files are intended to be included in other PostScript programs, so they need to be resized by the application generating the PostScript.
To that end, EPS files include comments (which are ignored by PostScript interpreters) which define the BoundingBox of the EPS. An application which places EPS can quickly scan the EPS to find this information, then it sets the CTM appropriately in the final PostScript program it is creating and inserts the content of the EPS.
The FitPage switch in Ghostscript relies on having a known media size (and you should set -dFIXEDMEDIA when using this) and a requested media size, figuring out what scale factor to apply to the request in order to make it fit the actual size, and setting up the CTM to apply that scaling.
If you don't ever get a media size request (which you won't with an EPS) then no scaling will take place.
Now Ghostscript does have a different switch, EPSCrop which picks up the comments from the EPS and uses that to set the media size (Ghostscript has mechanisms to permit processing of comments for this reason, amongst others). You could implement a similar mechanism to pick up the BoundingBox comments, and scale the EPS so that it fits a desired target media size.
I could probably knock something up, but I'd have to mess around creating an example file to work from.....
Do not accidentally specify PDFFitPage in the command line above. Specify EPSFitPage when dealing with EPS files. PDFFitPage will silently do nothing.

Making the "Region of Interest" (ROI) transparent in MATLAB

I've already made a function to cut out the image, and the part I cut out has a black background. I'm trying to make the black part transparent, then I can generate an image sequence that I can create a video with. I've tried converting the image to a double and then replacing the 0 values with NaN:
J = imread('imgExample.jpg');
J2 = im2double(J);
J2(J2 == 0) = NaN;
imwrite(J2, 'newImg.jpg');
but when I convert it into a video, it doesn't seem to stay. Is there any way to get the black part of the image to be transparent?
From clarifications in comments, you are trying to create a video format that supports alpha transparency using matlab.
In general this seems impossible using matlab alone (at least in matlab 2013 which is the version I use). If you'd like to check if the newest matlab supports videos with alpha transparency, type doc videowriter and have a look at the available formats. If you see anything with transparency options there, take it from there. But the most I see on mine is 24bit RGB videos (i.e. three channels, no transparency).
So matlab does not have the ability to produce native .avi video with alpha transparency.
However, note that this is a very rare video format anyway, and even if you did manage to produce such a video, you would still have to find a suitable viewer which supports playing videos with transparency!
It's therefore important for you to tell us your particular use-case because it may be you're actually trying to do something much simpler (which may or may not be solvable via matlab) (i.e. a case of the XY Problem
E.g. you may be trying to create a video with transparency for the web instead, like here https://developers.google.com/web/updates/2013/07/Alpha-transparency-in-Chrome-video
If this is the case, then I would recommend you attempting the method outlined there; you can create individual .png "frames" with transparency in matlab using the imwrite function. have a look at its documentation, particularly the section about png images and the 'Alpha' property. But beyond that, you'd need an external tool to combine them into a .webm file, since matlab doesn't seem to have a tool like that (at least none that I can see at a glance; there might be a 3rd-party toolkit if you look on the web).
Hope this helps.

How to improve the quality (smoothness) of lines in contourplots Matlab's

How the line smoothness in a contour plot can be improved for publications? For instance, the dotted lines look really bad, the continuous lines look as if their thickness varies. See below
Here's part of the code:
Vals = [0:5:200]; contourf(X,Y,W,Vals,'EdgeColor','k','LineWidth',1.2,'LineStyle',':');axis square;grid;hold on
Vals = [10:10:200]; contour(X,Y,W,Vals,'EdgeColor','k','LineWidth',1.2);
Vals = [20 : 20 : 200]; [C,h] = contour(X,Y,W,Vals,'Color','k','LineWidth',1.8);
clabel(C,h,'FontName','Palatino Linotype','FontAngle','italic','Fontsize',9,'Color','w')
print -djpeg -r300 filename
Thanks!
Saved as png doesn't help much... check the lines :/ See below:
Check the dotted lines now...
Here's saving as eps (-r1200)... it looks better
Exporting as vector graphics will definitely improve the image over what you see on your screen; I use LaTeX for publications and you can either export to eps for postscript output, and use epstopdf for PDF output, and embed these directly in your document; that would be the best solution.
Additionally, there are also a bunch of general utilities for making your plots look better for camera-ready publications, the most notable that comes to mind is exportfig, which has a load of features to help even with pixel graphics. These go above and beyond just generating smoother-looking images.
http://www.mathworks.us/matlabcentral/fileexchange/23629-exportfig
(copied from that page):
This function saves a figure or single axes to one or more vector and/or bitmap file formats, and/or outputs a rasterized version to the workspace, with the following properties:
Figure/axes reproduced as it appears on screen
Cropped borders (optional)
Embedded fonts (pdf only)
Improved line and grid line styles
Anti-aliased graphics (bitmap formats)
Render images at native resolution (optional for bitmap formats)
Transparent background supported (pdf, eps, png)
Semi-transparent patch objects supported (png only)
RGB, CMYK or grayscale output (CMYK only with pdf, eps, tiff)
Variable image compression, including lossless (pdf, eps, jpg)
Optionally append to file (pdf, tiff)
Vector formats: pdf, eps
Bitmap formats: png, tiff, jpg, bmp, export to workspace
This function is especially suited to exporting figures for use in publications and presentations, because of the high quality and portability of media produced.
Update: I see your example code now. Did you try changing -r300 to some really high value? More pixels per inch should make everything look smoother. For publication, crank it up really high, like -r1200.
Original:
One thing you can try is exporting the plot in some format that supports vector graphics. Matlab supports both PDF and EMF, so try one of those. Export using the saveas command or from the figure's "File -> Save as" menu item. After that, open or import the image file in some other application and hopefully it will look better.
Please add a new screenshot if you get a nicer image!

Matlab: How to save plots of patches / fill() automatically in the code?

quick question: I'm creating "random" polygons using either the patch() or the fill() function in Matlab. This works quite good and it is plotted correctly.
However, I need to at least save a few hundres polygons as images to my hard drive for working with them later - so I'm looking for a way to directly save the image in my function rather than saving each polygon myself using the file-menu.
Is there any way to do this?
Thanks in advance!
You can indeed use the print function, but I would not use the jpeg device. JPEG is never the right format for plots (you will get a lot of artifacts near all your lines).
If you need a bitmap image, try the png or tiff device. If you don't need a bitmap, use the appropriate vector image format: fig is the native MATLAB format (which allows you to edit the plot afterwards), so this is the best one if you stick with MATLAB for all your operations. For exporting to other software, I would recommend pdf (works almost anywhere), epsc (EPS with color, great for LaTeX or inkscape), wmf/emf (Windows Metafile, so Windows only, but great for including the images in MS Office). Or you could of course use any of the other formats mentioned in the print documentation.
Sometimes it's a pain in the neck to get the format of your image all right (especially with PDF output). Just take a look at the different properties of your figure and more specifically the PaperSize, PaperUnits and PaperPosition.
The easiest way, and I guess the best solution, is to save as a .fig file. You can do this by using saveas:
h = figure;
% your plot commands here
saveas(h,'mFile.fig');
Afterwards, you can reload the image with the openfig function:
openfig('mFile.fig');
Have to add this answer. This function is helping a lot.
This function saves a figure or single axes to one or more vector and/or bitmap file formats, and/or outputs a rasterized version to the workspace, with the following properties:
   - Figure/axes reproduced as it appears on screen
   - Cropped/padded borders (optional)
   - Embedded fonts (pdf only)
   - Improved line and grid line styles
   - Anti-aliased graphics (bitmap formats)
   - Render images at native resolution (optional for bitmap formats)
   - Transparent background supported (pdf, eps, png)
   - Semi-transparent patch objects supported (png only)
   - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tiff)
   - Variable image compression, including lossless (pdf, eps, jpg)
   - Optionally append to file (pdf, tiff)
   - Vector formats: pdf, eps
   - Bitmap formats: png, tiff, jpg, bmp, export to workspace