Technology

Show Only ...
Maps - Photos - Videos

Code Scrap for Exporting a Map to a Raster PDF

A follow up to yesterday's post about Vector export of QGIS Composers using PyQGIS. This does the export as a Raster PDF, for much smaller files but with the same or better quality.

I don’t like the vector Adobe Acrobat PDF that Quantum GIS exports by default if you don’t specifically check “Export as Raster” in the Composer View. It’s true that Vector PDF is a higher quality, but the files are much larger and slower loading. A 300 DPI raster PDF file will suffice for most printing needs.

I struggled for a number of days to figure out the best way to export a Raster PDF from Quantum GIS with PyQGIS. I ended up giving up, preferring to just export a high-resolution JPEG and convert the JPEG to a Adobe PDF using ImageMagick’s convert command. It gave me much smaller PDF files due to higher compression then what you get through the PDF export built into QGIS’s Composers with the “Export as Raster” checked.

When you use printPageAsRaster(0), all settings related to resolution are preserved in the exported file (such as 300 DPI format and 8×10 page size), so ImageMagick automatically converts it over.

You don’t have to include all the libraries that are listed below, I was lazy, and I needed all of them for my map automation plugin, so I left them in. You should remove the ones you don’t use. Don’t forget to change the composer name from Horizontal to the composer you use, and adjust the output paths accordingly.

It may not be elegant, but it works well. This is my solution, it may not be yours.

from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication,QFileInfo,QSizeF
from PyQt4.QtGui import QAction, QIcon, QPrinter,QPainter
from os import sys 

composerId = 0
composers = iface.activeComposers()
for item in composers:
	if item.composerWindow().windowTitle() == 'Horizontal':
		break
	composerId += 1

c = composers[composerId].composition()

image = c.printPageAsRaster(0)
image.save("/tmp/"+QgsProject.instance().title()+".jpg", "jpg")
os.system('convert "/tmp/'+QgsProject.instance().title()+'.jpg" "/tmp/'+QgsProject.instance().title()+'.pdf"')

Evening Down in the Ravine

Code Scrap for Exporting a QGIS Composer to a Vector PDF

I had trouble finding a clear example online of how to export a composer file as a Vector Adobe Acrobat PDF you have loaded in Quantum GIS via a Python plugin or script. This code that I put together does the trick.

This is the traditional method of Python Scripting to export a QGIS Composer as an Adobe Acrobat PDF file. This produces a vector PDF file regardless of your setting under “Print as a Raster”. This provides the highest quality print output, but may cause incorrect rendering if you use effects like multiply layers. Tomorrow I will post code I use for making PDFs, using compressed (but high resolution) Raster JPEG files embedded in the PDF files.

It’s possible you won’t need to import as many classes as I did. I just didn’t carefully go through the list to remove classes that are unnecessary (as they are neccessary for my plugin code). You will need to adjust the output file name and the window title for the Composer to whatever you named your Composer as. Remember if you use this in a plugin class, to make iface to self.iface or this code won’t work. Stupid stuff like that will trip you up.

from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication,QFileInfo,QSizeF
from PyQt4.QtGui import QAction, QIcon, QPrinter,QPainter

composerId = 0
composers = iface.activeComposers()
for item in composers:
	if item.composerWindow().windowTitle() == 'Horizontal':
		break
	composerId += 1

c = composers[composerId].composition()

image = c.printPageAsRaster(True, QSize(),c.printResolution())

printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("/tmp/"+QgsProject.instance().title()+".pdf")
printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(c.printResolution())

pdfPainter = QPainter(printer)
c.renderPage(pdfPainter,0)
pdfPainter.end()

I hope this is helpful. I’m not a real PyQGIS pro, but if you have ideas or comments, please add them below.

Rensslear Plateau

Moon Cycle Function

People have asked what code I use to get the moon cycle data on my blog. A while back I found some BASIC code that did the job and ported it over PHP for ease of use with my Wordpress based blog. Here is the code that you can use as needed.

function moon_cycle($time) {
    // calcuates where a day is in moon's cycle
    //     
    // input:    time in seconds since epoch
    // ouput:    0 to <2 where:
    //           new moon = 0, waxing moon = .5, 
    //           full moon = 1, waining moon = 1.5
    // requires: none
    // based on: http://www.voidware.com/moon_phase.htm
    // and also: http://mikesmith.com/blog.html

    $year = date('Y', $time);
    $month = date('m', $time);
    $day = date('d', $time);

    $c = $e = $jd = $b = 0;
    if ($month < 3) {
        $year--;
        $month += 12;
    }
    ++$month;
    $c = 365.25 * $year;     // avg days per year
    $e = 30.6 * $month;     // avg days per month
    $jd = $c + $e + $day - 694039.09;  // jd is total days elapsed
    $jd /= 29.5305882;      // divide by the moon cycle
    $b = (int) $jd;      // int(jd) -> b, take integer part of jd
    $jd -= $b;        // subtract integer part to leave 

    return $jd * 2;
}