2

ダウンロードしたいPNG画像リンクがいくつかあり、「サムネイルに変換」し、PythonとCairoを使用してPDFに保存します。

これで、動作するコードができましたが、用紙上の画像サイズを制御する方法がわかりません。PyCairo Surface のサイズを希望のサイズに変更する方法はありますか (元のサイズよりも小さくなっています)。元のピクセルを(紙の上で)より高い解像度に「縮小」したい。

また、Image.rescale()PIL の関数を試しましたが、20x20 ピクセルの出力が返されます (200x200 ピクセルの元の画像から、コードのバナーの例ではありません)。私が欲しいのは、紙の上の20x20 mmの正方形の中にプロットされた200x200ピクセルの画像です(私が今得ている200x200 mmの正方形ではなく)

私の現在のコードは次のとおりです。

#!/usr/bin/python

import cairo, urllib, StringIO, Image   # could I do it without Image module?

paper_width = 210
paper_height = 297
margin = 20

point_to_milimeter = 72/25.4

pdfname = "out.pdf" 
pdf = cairo.PDFSurface(pdfname , paper_width*point_to_milimeter, paper_height*point_to_milimeter)
cr = cairo.Context(pdf)
cr.scale(point_to_milimeter, point_to_milimeter)

f=urllib.urlopen("http://cairographics.org/cairo-banner.png")
i=StringIO.StringIO(f.read())
im=Image.open(i)

# are these StringIO operations really necessary?

imagebuffer = StringIO.StringIO()  
im.save(imagebuffer, format="PNG")
imagebuffer.seek(0)
imagesurface = cairo.ImageSurface.create_from_png(imagebuffer)


### EDIT: best answer from Jeremy, and an alternate answer from mine:
best_answer = True      # put false to use my own alternate answer
if best_answer:
    cr.save()
    cr.scale(0.5, 0.5)
    cr.set_source_surface(imagesurface, margin, margin)
    cr.paint()
    cr.restore()
else:
    cr.set_source_surface(imagesurface, margin, margin)
    pattern = cr.get_source()
    scalematrix = cairo.Matrix()    # this can also be used to shear, rotate, etc.
    scalematrix.scale(2,2)          # matrix numbers seem to be the opposite - the greater the number, the smaller the source
    scalematrix.translate(-margin,-margin)  # this is necessary, don't ask me why - negative values!!
    pattern.set_matrix(scalematrix)  
    cr.paint()  

pdf.show_page()

美しい Cairo バナーはページに収まらないことに注意してください... 理想的な結果は、この画像の幅と高さをユーザー空間単位 (この場合はミリメートル) で制御して、素敵なヘッダー画像を作成できることです。例えば。

読んでくれて、助けてくれたりコメントしてくれてありがとう!!

4

3 に答える 3

2

画像を描画するときにコンテキストをスケーリングしてみてください。

例えば

cr.save()    # push a new context onto the stack
cr.scale(0.5, 0.5)    # scale the context by (x, y)
cr.set_source_surface(imagesurface, margin, margin)
cr.paint()
cr.restore()    # pop the context

詳細については、http: //cairographics.org/documentation/pycairo/2/reference/context.htmlを参照してください。

于 2011-08-18T04:20:00.170 に答える
0

Jeremy Flores は、イメージ サーフェスをソースとして設定する前にターゲット サーフェスをスケーリングすることで、私の問題を非常にうまく解決しました。とはいえ、いつか実際に Surface のサイズを変更する (または何らかの方法で変換する) 必要があるかもしれないので、ドキュメントを完全に読んだ後に推測される別の回答 (既に質問に含まれています) で使用される理論的根拠を簡単に説明します。

  1. サーフェスをコンテキストのソースとして設定します - 暗黙的にcairo.Pattern!!を作成します
  2. Context.get_source()パターンを元に戻すために使用します。
  3. を作成しcairo.Matrixます。
  4. このマトリックス (すべての変換を含む) をパターンに適用します。
  5. ペイント!

唯一の問題は、原点の周りで常に動作する変換であるように思われるため、スケーリングと回転の前に原点への補完的な変換が必要です (bleargh)。

于 2011-08-18T04:58:27.997 に答える