Programmatically adding Images to RTF Document

后端 未结 5 642
时光说笑
时光说笑 2020-11-27 04:40

I am trying to add a image to a RTF document which I am creating. I would prefer to not use \'copy/paste\' methods (that involve pasting the image within a RichTextBox and t

5条回答
  •  难免孤独
    2020-11-27 05:11

    Later visitors to this page (such as I was a few days ago) may find the following link useful: Convert an image into WMF with .NET

    One will find that WordPad ignores any image not stored in the proper Windows MetaFile format. Thus, the previous example on this page will not show up at all (Even though it works just fine in OpenOffice and Word itself). The format that WordPad WILL support is:

    {/pict/wmetafile8/picw[width]/pich[height]/picwgoal[scaledwidth]/pichgoal[scaledheight] [image-as-string-of-byte-hex-values]} (with terms in square brackets replaced with the appropriate data).

    Getting the 'appropriate data' can be done by following the procedures in the above link. For those with python looking for a solution, here is the start of one (I believe some dpi/scaling issues remain). This requires PIL(or Pillow), ctypes, and clr (Python .NET). Use PIL/Pillow and open up the image first. Here I have it open as "canv":

    from ctypes import *
    import clr
    clr.AddReference("System.IO")
    clr.AddReference("System.Drawing")
    from System import IntPtr
    from System.Drawing import SolidBrush
    from System.Drawing import Color
    from System.Drawing import Imaging
    from System.Drawing import Graphics
    from System.IO import FileStream
    from System.IO import FileMode
    from System.IO import MemoryStream
    from System.IO import File
    
    def byte_to_hex(bytefile):
      acc = ''
      b = bytefile.read(1)
      while b:
        acc+=("%02X" % ord(b))
        b = bytefile.read(1)
      return acc.strip()
    
    #... in here is some code where 'canv' is created as the PIL image object, and
    #...   'template' is defined as a string with placeholders for picw, pich, 
    #...   picwgoal, pichgoal, and the image data
    
    
    mfstream     = MemoryStream()
    offscrDC     = Graphics.FromHwndInternal(IntPtr.Zero)
    imgptr       = offscrDC.GetHdc()
    mfile        = Imaging.Metafile(mfstream, imgptr, Imaging.EmfType.EmfOnly)
    gfx          = Graphics.FromImage(mfile)
    width,height = canv.size
    pixels       = canv.load()
    for x in range(width):
      for y in range(height):
        _r,_g,_b = pixels[x, y]
        c     = Color.FromArgb(_r, _g, _b)
        brush = SolidBrush(c)
        gfx.FillRectangle(brush, x, y, 1, 1)
    gfx.Dispose()
    offscrDC.ReleaseHdc()
    _hEmf            = mfile.GetHenhmetafile()
    GdipEmfToWmfBits = windll.gdiplus.GdipEmfToWmfBits
    _bufferSize      = GdipEmfToWmfBits(
                          int(str(_hEmf)),
                          c_uint(0),
                          None,
                          c_int(8),           # MM_ANISOTROPIC
                          c_uint(0x00000000)) # Default flags
    _buffer = c_int * _bufferSize
    _buffer = _buffer(*[0 for x in range(_bufferSize)])
    GdipEmfToWmfBits( int(str(_hEmf)),
                      c_uint(_bufferSize),
                      _buffer,
                      c_int(8),            # MM_ANISOTROPIC
                      c_uint(0x00000000) ) # Default flags
    hmf = windll.gdi32.SetMetaFileBitsEx(c_uint(_bufferSize), _buffer)
    windll.gdi32.CopyMetaFileA(int(str(hmf)), "temp.wmf")
    windll.gdi32.DeleteMetaFile(int(str(hmf)))
    windll.gdi32.DeleteEnhMetaFile(int(str(_hEmf)))
    mfstream.Close()
    
    imgstr = open("temp.wmf", 'rb')
    imgstr = byte_to_hex(imgstr)
    with open('script-out.rtf','wb') as outf:
      template = template % (str(_cx),str(_cy),str(15*_cx),str(15*_cy),imgstr)
      outf.write(template)
    

提交回复
热议问题