Domanda

Sto cercando di aggiungere un'immagine a un documento RTF che sto creando. Io preferirei non usare metodi 'copia / incolla' (che coinvolgono incollare l'immagine all'interno di un RichTextBox e quindi di accesso a proprietà .RTF), che spurgare il clipboard (in quanto questo sarà un fastidio e confusione per i miei utenti finali).

Il codice che ho finora restituisce la stringa che deve essere inserito nel documento RTF per stampare l'immagine. L'immagine immesso (che si trova a $ path) è di solito in formato jpeg o bmp, ma in questa fase io non sono interessato a come l'immagine viene memorizzata all'interno del RTF unica che posso farlo funzionare.

public string GetImage(string path, int width, int height)
{
    MemoryStream stream = new MemoryStream();
    string newPath = Path.Combine(Environment.CurrentDirectory, path);
    Image img = Image.FromFile(newPath);
    img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);

    byte [] bytes = stream.ToArray();

    string str = BitConverter.ToString(bytes, 0).Replace("-", string.Empty);
    //string str = System.Text.Encoding.UTF8.GetString(bytes);

    string mpic = @"{\pict\pngblip\picw" + 
        img.Width.ToString() + @"\pich" + img.Height.ToString() +
        @"\picwgoa" + width.ToString() + @"\pichgoa" + height.ToString() + 
        @"\hex " + str + "}";
    return mpic
}

Tuttavia, il problema è che questo codice non funziona perché per quanto posso dire, la stringa str non ha la conversione stringa corretta per lavorare all'interno del RTF.

Modifica: Il mio problema mancava uno spazio dopo la \ hex in @ "\ hex" e, inoltre, non escludendo i - personaggi dal valore restituito del BitConverter

""
È stato utile?

Soluzione

provare questi collegamenti

è necessario modificare "picwgoa" a "picwgoal" e "pichgoa" a "pichgoal"

string mpic = @"{\pict\pngblip\picw" + 
    img.Width.ToString() + @"\pich" + img.Height.ToString() +
    @"\picwgoal" + width.ToString() + @"\pichgoal" + height.ToString() + 
    @"\bin " + str + "}";

Ecco una lista dei formati immagine supportati

\emfblip      Source of the picture is an EMF (enhanced metafile).
\pngblip      Source of the picture is a PNG.
\jpegblip     Source of the picture is a JPEG.
\shppict      Specifies a Word 97-2000 picture. This is a destination control word.
\nonshppict   Specifies that Word 97-2000 has written a {\pict destination that it will not read on input. This keyword is for compatibility with other readers.
\macpict      Source of the picture is QuickDraw.
\pmmetafileN  Source of the picture is an OS/2 metafile. The N argument identifies the metafile type. The N values are described in the \pmmetafile table below.
\wmetafileN   Source of the picture is a Windows metafile. The N argument identifies the metafile type (the default is 1).
\dibitmapN    Source of the picture is a Windows device-independent bitmap. The N argument identifies the bitmap type (must equal 0).The information to be included in RTF from a Windows device-independent bitmap is the concatenation of the BITMAPINFO structure followed by the actual pixel data.    
\wbitmapN     Source of the picture is a Windows device-dependent bitmap. The N argument identifies the bitmap type (must equal 0).The information to be included in RTF from a Windows device-dependent bitmap is the result of the GetBitmapBits function.

Altri suggerimenti

Abbiamo trascorso un giorno o poco più googling risposte per questo. Messo insieme curiosità da tutto StackOverflow e da altre fonti. Alimentare questo un'immagine, tornerà la stringa è necessario aggiungere al proprio interno richtextbox.rtf. I cambiamenti larghezza e deve essere calcolato, la formula è dato.

    // RTF Image Format
    // {\pict\wmetafile8\picw[A]\pich[B]\picwgoal[C]\pichgoal[D]
    //  
    // A    = (Image Width in Pixels / Graphics.DpiX) * 2540 
    //  
    // B    = (Image Height in Pixels / Graphics.DpiX) * 2540 
    //  
    // C    = (Image Width in Pixels / Graphics.DpiX) * 1440 
    //  
    // D    = (Image Height in Pixels / Graphics.DpiX) * 1440 

    [Flags]
    enum EmfToWmfBitsFlags
    {
        EmfToWmfBitsFlagsDefault = 0x00000000,
        EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
        EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
        EmfToWmfBitsFlagsNoXORClip = 0x00000004
    }

    const int MM_ISOTROPIC = 7;
    const int MM_ANISOTROPIC = 8;

    [DllImport("gdiplus.dll")]
    private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, uint _bufferSize,
        byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
    [DllImport("gdi32.dll")]
    private static extern IntPtr SetMetaFileBitsEx(uint _bufferSize,
        byte[] _buffer);
    [DllImport("gdi32.dll")]
    private static extern IntPtr CopyMetaFile(IntPtr hWmf,
        string filename);
    [DllImport("gdi32.dll")]
    private static extern bool DeleteMetaFile(IntPtr hWmf);
    [DllImport("gdi32.dll")]
    private static extern bool DeleteEnhMetaFile(IntPtr hEmf);

        public static string GetEmbedImageString(Bitmap image)
        {
                Metafile metafile = null;
                float dpiX; float dpiY;

                using (Graphics g = Graphics.FromImage (image)) 
                {
                    IntPtr hDC = g.GetHdc ();
                    metafile = new Metafile (hDC, EmfType.EmfOnly);
                    g.ReleaseHdc (hDC);
                }

                using (Graphics g = Graphics.FromImage (metafile)) 
                {
                    g.DrawImage (image, 0, 0);
            dpiX = g.DpiX;
            dpiY = g.DpiY;
                }

                IntPtr _hEmf = metafile.GetHenhmetafile ();
                uint _bufferSize = GdipEmfToWmfBits (_hEmf, 0, null, MM_ANISOTROPIC,
                EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
                byte[] _buffer = new byte[_bufferSize];
                GdipEmfToWmfBits (_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
                                            EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
                IntPtr hmf = SetMetaFileBitsEx (_bufferSize, _buffer);
                string tempfile = Path.GetTempFileName ();
                CopyMetaFile (hmf, tempfile);
                DeleteMetaFile (hmf);
                DeleteEnhMetaFile (_hEmf);

                var stream = new MemoryStream ();
                byte[] data = File.ReadAllBytes (tempfile);
                //File.Delete (tempfile);
                int count = data.Length;
                stream.Write (data, 0, count);

                string proto = @"{\rtf1{\pict\wmetafile8\picw" + (int)( ( (float)image.Width / dpiX ) * 2540 )
                                  + @"\pich" + (int)( ( (float)image.Height / dpiY ) * 2540 )
                                  + @"\picwgoal" + (int)( ( (float)image.Width / dpiX ) * 1440 )
                                  + @"\pichgoal" + (int)( ( (float)image.Height / dpiY ) * 1440 )
                                  + " " 
                      + BitConverter.ToString(stream.ToArray()).Replace("-", "")
                                  + "}}";                   
                return proto;
        }

i visitatori più tardi per questa pagina (ad esempio, ero a pochi giorni fa) potrebbe trovare il seguente link utili: convertire un'immagine in WMF con .NET

Si troverà che WordPad ignora qualsiasi immagine non memorizzato nel corretto Windows Metafile Format. Così, nell'esempio precedente in questa pagina non verrà mostrato a tutti (anche se funziona bene in OpenOffice e Word stesso). Il formato che WordPad sosterrà è:

{/ fig / wmetafile8 / picw [larghezza] / pinch [altezza] / picwgoal [scaledwidth] / pichgoal [scaledheight] [image-as-stringa di byte-valori-hex]} (con termini tra parentesi quadre sostituiti con i dati appropriati).

Per la 'dati appropriato' può essere fatto seguendo le procedure nel link qui sotto. Per quelli con python alla ricerca di una soluzione, qui è l'inizio di una (credo che rimangono alcuni problemi dpi / scala). Ciò richiede PIL (o Cuscino ), ctypes e CLR (Python NET) . Utilizzare PIL / cuscino e di aprire la prima immagine. Qui l'ho aperta come "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)

Ho trovato che la maggior parte delle scatole RTF utilizzando il seguente formato:

{\object\objemb{\*\objclass Paint.Picture}\objw2699\objh4799{\*\objdata [hex/bin]}}

Quando [hex/bin] è grande quantità di stringhe esadecimali che rappresentano il formato dell'immagine. In questo modo lavorare sia per rtf Word, e sia per la scatola RTF - quindi è più efficiente.

Nella mia immagine del computer in una dimensione di 180x320 pixel 2699x4799 stato convertito in twip, il che significa 1pix = 15 twips, per quanto posso vedere, è come questo in 3 computer che ho provato, tra di loro WinXP prof, casa di WinXP e Win 7.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top