The scale will inevitably effect the extent for any given area and that will be limited by the size of your paper (so an A4 sheet @ 1:50,000 scale will be approximately a half of the possible extent of an A3 sheet). Contrariwise, setting the map extent for a given area of paper will also inevitable dictate the scale. You cannot adjust one without influencing the other (which is why you have received some negative scores for this question).
You have stated that your actual extent is not as important as scale. So to resolve your dilemma, set the scale and then, with the map selected, click the 'Move item content' button (icon is a small arrow and green box, next to the 'Select/Move item' button - a large arrow).
You can now 'slide' the content of the map without changing the position of the map on the page and thereby center you map contents on your area of interest.
If the extent of the map is still not large enough at the scale you must use, then you need to increase the size of the map and that might mean splitting your map over two or more sheets and to do that effectively you can use the Atlas generator.
You can set the page background to transparent by creating a transparent symbol and setting the page background to use that symbol:
transparent_fill = QgsFillSymbolV2.createSimple({ 'outline_style': 'no', 'style': 'no'})
c.setPageStyleSymbol( transparent_fill )
There's also a few other things wrong with your script:
First,
mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
mapRenderer is deprecated and will be removed soon. The replacement is QgsMapSettings:
map_settings = iface.mapCanvas().mapSettings()
c = QgsComposition(map_settings)
Next,
# get all items and disable the backgrounds
itemList = c.items()
c.removeItem(itemList[2])
c.removeItem(itemList[2])
itemList[2].setBackgroundEnabled(False)
itemList[3].setBackgroundEnabled(False)
# add them to the composition
c.addItem(itemList[2])
c.addItem(itemList[3])
c.refreshItems()
c.refreshDataDefinedProperty(QgsComposerObject.AllProperties)
Most of this isn't required. Just set the map item to have no background after you've created it:
composerMap = QgsComposerMap(c, x ,y, w, h)
composerMap.setBackgroundEnabled(False)
Lastly:
# image = QImage(QSize(width, height), QImage.Format_ARGB32)
image = QImage(QSize(width, height), QImage.Format_ARGB32_Premultiplied)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
#image.fill(0)
Should be:
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill( Qt.transparent )
Don't use a premultiplied image, and you MUST initialise the image with a color. In this case we'll initialise it by filling it with a transparent color.
Here's a working (and cleaned up) version:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# PARAMETERS
mainPath = '/path/to/folder/'
filename = 'filename'
imageType = "png"
imageWidth_mm = 400
imageHeight_mm = 160
dpi = 300
map_settings = iface.mapCanvas().mapSettings()
c = QgsComposition(map_settings)
c.setPaperSize(400, 160)
c.setPrintResolution(dpi)
#set page background to transparent
transparent_fill =QgsFillSymbolV2.createSimple({ 'outline_style': 'no', 'style': 'no'})
c.setPageStyleSymbol( transparent_fill )
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x ,y, w, h)
composerMap.setBackgroundEnabled(False)
c.addItem(composerMap)
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())
# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(Qt.transparent)
imagePainter = QPainter(image)
c.setPlotStyle(QgsComposition.Print)
c.renderPage( imagePainter, 0 )
imagePainter.end()
imageFilename = mainPath + filename + '.' + imageType
image.save(imageFilename, imageType)
print 'image saved'
print 'done'
Best Answer
You can use the following to resize the map canvas:
You need to import
QSize
before being able to use it. Although you seem to be correct in that it was depreciated.