Autor Téma: Převod JPG do RxRichEditu  (Přečteno 9088 krát)

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Převod JPG do RxRichEditu
« Odpověď #30 kdy: 14-01-2014, 23:47:46 »
Pane Janoto, zas až tak tenký ten led není. Minimálně předpokládám, že si pročítáte vlastní vlákna a snažíte se pochopit kód, který píšete :)

Projděte si to ještě jednou a zamyslete se nad tím, proč vaše funkce StreamToString je nesmyslná.
Embarcadero Technology Partner

RadekJanota

  • Host
Re:Převod JPG do RxRichEditu
« Odpověď #31 kdy: 15-01-2014, 09:03:32 »
Tím tenkým ledem jsem měl na mysli, že jsem opravdový začátečník a programuji teprve pár týdnů, takže se v tom opravdu zatím moc neorientuji. Zkusil jsem tu funkci předělat, ale výsledek je naprosto stejný.

Kód: Delphi [Vybrat]
  1. function StreamToString(M: TMemoryStream): string;
  2. begin
  3.   SetString(Result, PChar(M.Memory), M.Size div (SizeOf(Char))  );
  4. end;


Prosím, poraďte blbci trochu více.

Moc děkuji.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3004
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Převod JPG do RxRichEditu
« Odpověď #32 kdy: 15-01-2014, 09:29:46 »
Musíš ten stream prohnal přes tu konverzi na hex. Stream je jen řada byte, tj. každý byte musíš nahradit za jejich hexa reprezentaci tak jak jsi to psal někde v prvním příspěvku.
Embarcadero MVP - Czech republic

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Převod JPG do RxRichEditu
« Odpověď #33 kdy: 15-01-2014, 09:53:01 »
Radek vám už odpověděl. Já jsem se bál, že naše odpovědi vůbec nečtete (viz posty #8, #12, #25)...

Trochu jsem hledal v Googlu a zjistil jsem, že JvRichEdit.pas z http://www.delphi-jedi.org/ už má v sobě hotový kód přesně na to, co potřebujete. Viz funkce BitmapToRTF a BitmapToRTF2:

Kód: Delphi [Vybrat]
  1.   { Two procedures to construct RTF from a bitmap. You can use this to
  2.     insert bitmaps in the rich edit control, for example:
  3.  
  4.       Stream := TMemoryStream.Create;
  5.       try
  6.         BitmapToRTF(SomeBitmap, Stream);
  7.         Stream.Position := 0;
  8.  
  9.         JvRichEdit1.StreamFormat := sfRichText;
  10.         JvRichEdit1.StreamMode := [smSelection, smPlainRtf];
  11.         JvRichEdit1.Lines.LoadFromStream(Stream);
  12.       finally
  13.         Stream.Free;
  14.       end;
  15.  
  16.     But:
  17.  
  18.     * if you stream out the RTF content of the rich edit control, the bitmaps
  19.       are *not* included. Use TJvRichEdit.InsertGraphic if you want the bitmaps
  20.       to be included in the RTF.
  21.     * TJvRichEdit.AllowObjects must be set to True.
  22.     * BitmapToRTF is the fastest, TJvRichEdit.InsertGraphic the slowest.
  23.   }
  24.  
  25. { uses the \dibitmap identifier }
  26. procedure BitmapToRTF(ABitmap: TBitmap; AStream: TStream);
  27. { uses the \wmetafile identifier }
  28. function BitmapToRTF2(ABitmap: TBitmap; AStream: TStream): Boolean;
  29.  

Kód: Delphi [Vybrat]
  1. procedure BitmapToRTF(ABitmap: TBitmap; AStream: TStream);
  2. const
  3.   CPrefix = '{\rtf1 {\pict\picw%d\pich%d\dibitmap0 ';
  4.   CPostfix = AnsiString(' }}');
  5. var
  6.   Header, Bits: PAnsiChar;
  7.   HeaderSize, BitsSize: DWORD;
  8.   P, Q: PAnsiChar;
  9.   S: AnsiString;
  10. begin
  11.   GetDIBSizes(ABitmap.Handle, HeaderSize, BitsSize);
  12.   GetMem(Header, 2 * (HeaderSize + BitsSize));
  13.   try
  14.     Bits := Header + HeaderSize;
  15.     GetDIB(ABitmap.Handle, ABitmap.Palette, Header^, Bits^);
  16.  
  17.     { Example :
  18.  
  19.       HeaderSize = 2, BitsSize = 2
  20.  
  21.       Header = $AB, $00, $DE, $F8, ?? , ?? , ?? , ??
  22.       ->
  23.       Header = 'A', 'B', '0', '0', 'D', 'E', 'F', '8'
  24.     }
  25.     Q := Header + HeaderSize + BitsSize - 1;
  26.     //P := Header + 2 * (HeaderSize + BitsSize) - 1;
  27.     P := Q + HeaderSize + BitsSize;
  28.     while Q >= Header do
  29.     begin
  30.       P^ := CHex[Byte(Q^) mod 16];
  31.       Dec(P);
  32.       P^ := CHex[Byte(Q^) div 16];
  33.       Dec(P);
  34.       Dec(Q);
  35.     end;
  36.     S := AnsiString(Format(CPrefix, [ABitmap.Width, ABitmap.Height]));
  37.     AStream.Write(PAnsiChar(S)^, Length(S));
  38.     AStream.Write(Header^, (HeaderSize + BitsSize) * 2);
  39.     AStream.Write(CPostfix, Length(CPostfix));
  40.   finally
  41.     FreeMem(Header);
  42.   end;
  43. end;
  44.  
  45. function BitmapToRTF2(ABitmap: TBitmap; AStream: TStream): Boolean;
  46.  
  47. {
  48.  
  49.   \wmetafileN  - Source of the picture is a Windows metafile. The N argument
  50.                  identifies the metafile type (the default type is 1).
  51.   \picwN       - xExt field if the picture is a Windows metafile; picture
  52.                  width in pixels if the picture is a bitmap or from QuickDraw.
  53.                  The N argument is a long integer.
  54.   \pichN       - yExt field if the picture is a Windows metafile; picture
  55.                  height in pixels if the picture is a bitmap or from QuickDraw.
  56.                  The N argument is a long integer.
  57.   \picwgoalN   - Desired width of the picture in twips. The N argument is a
  58.                  long integer.
  59.   \pichgoalN   - Desired height of the picture in twips. The N argument is a
  60.                  long integer.
  61. }
  62.  
  63. const
  64.   CPrefix = '{\rtf1 {\pict\wmetafile8\picw%d\pich%d\picwgoal%d\pichgoal%d ';
  65.   CPostfix = AnsiString(' }}');
  66. var
  67.   P, Q: PAnsiChar;
  68.   S: AnsiString;
  69.   DC: HDC;
  70.   MetafileHandle: HMETAFILE;
  71.   Size: TPoint;
  72.   BitsLength: UINT;
  73.   Bits: PAnsiChar;
  74. begin
  75.   Result := False;
  76.  
  77.   // Retrieve Extent
  78.   Size.X := MulDiv(ABitmap.Width, CHundredthMMPerInch, Screen.PixelsPerInch);
  79.   Size.Y := MulDiv(ABitmap.Height, CHundredthMMPerInch, Screen.PixelsPerInch);
  80.  
  81.   // Create Metafile DC and set it up
  82.   DC := CreateMetafile(nil);
  83.  
  84.   SetWindowOrgEx(DC, 0, 0, nil);
  85.   SetWindowExtEx(DC, Size.X, Size.Y, nil);
  86.  
  87.   StretchBlt(DC, 0, 0, Size.X, Size.Y,
  88.     ABitmap.Canvas.Handle, 0, 0, ABitmap.Width, ABitmap.Height, SRCCOPY);
  89.  
  90.   MetafileHandle := CloseMetaFile(DC);
  91.  
  92.   if MetafileHandle = 0 then
  93.     Exit;
  94.  
  95.   try
  96.     BitsLength := GetMetaFileBitsEx(MetafileHandle, 0, nil);
  97.     GetMem(Bits, BitsLength * 2);
  98.     try
  99.       if GetMetaFileBitsEx(MetafileHandle, BitsLength, Bits) < BitsLength then
  100.         Exit;
  101.  
  102.       Q := Bits + BitsLength - 1;
  103.       //P := Bits + 2 * BitsLength - 1;
  104.       P := Q + BitsLength;
  105.       while Q >= Bits do
  106.       begin
  107.         P^ := CHex[Byte(Q^) mod 16];
  108.         Dec(P);
  109.         P^ := CHex[Byte(Q^) div 16];
  110.         Dec(P);
  111.         Dec(Q);
  112.       end;
  113.  
  114.       S := AnsiString(Format(CPrefix, [Size.X, Size.Y,
  115.         MulDiv(ABitmap.Width, CTwipsPerInch, Screen.PixelsPerInch),
  116.           MulDiv(ABitmap.Height, CTwipsPerInch, Screen.PixelsPerInch)]));
  117.       AStream.Write(PAnsiChar(S)^, Length(S));
  118.       AStream.Write(Bits^, BitsLength * 2);
  119.       AStream.Write(CPostfix, Length(CPostfix));
  120.  
  121.       Result := True;
  122.     finally
  123.       FreeMem(Bits, BitsLength * 2);
  124.     end;
  125.   finally
  126.     DeleteMetaFile(MetafileHandle);
  127.   end;
  128. end;
  129.  
« Poslední změna: 15-01-2014, 10:02:59 od oxo »
Embarcadero Technology Partner

RadekJanota

  • Host
Re:Převod JPG do RxRichEditu
« Odpověď #34 kdy: 15-01-2014, 11:21:42 »
Díky.
Tyto funkce z JvRichEdit.pas jsem už včera zkoušel. Fungují bezvadně, ale neřeší můj problém.
Obrázek se vloží bez problémů, ale pokud v RxRichEditu ručně (myší) změním jeho velikost, tak opět mám rozhozený ten výsledný obrázek, jak jsem psal výše v obrázku je taková divně barevná mozaika.

viz. obrázky:
https://drive.google.com/file/d/0B6FT6ZHCM3e9VEhrWEgyWGxSUVk/edit?usp=sharing
https://drive.google.com/file/d/0B6FT6ZHCM3e9bGlsWUJMQmZhb2c/edit?usp=sharing

Pokud udělám následující postup, tak je ten obrázek bez problémů a jde měnit jeho velikost bez sebemenší změny:

1) ve Wordpadu vytvořím RTF s obrázkem
2) z výsledného RTF souboru ručně vykopíruji tu část, která obsahuje pouze ta obrazová data a uložím třeba do memo1.text
3) v mém programu složím dohromady RTF

A: = '{\rtf1 {\pict\wmetafile8 ';
B: = ' }}';
Vysledek:=A+Memo1.Text+B;

4) tento výsledek vložím do RxRichEdit, tak je vše funkční a jde obrázek bez problémů měnit.

Zajímavé je, že pokud použiji ta obrazová data z Wordpadu, tak jsou přibližně 2x větší než velikost původního obrázku. Chová se to stejně i z Wordu a OpenOffice. Pokud to dělám přes výše zmíněné funkce, tak jsou ta obrazová data přibližně stejně velká jako velikost obrázku.
Z toho usuzuji, že Wordpad, MS Word i OpenOffice dělá ta metadata nějak jinak a proto mi to funguje.

Doufám, že jsem to popsal srozumitelně.

Díky za jakýkoliv nápad.








Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Převod JPG do RxRichEditu
« Odpověď #35 kdy: 15-01-2014, 11:35:53 »
To bude chtít zanalyzovat jaká data tam WordPad a spol. ukládá. Já se ve formátu WMF moc nevyznám, jsou ale tací, co se vyznají. Např. A. Bouchez z http://www.synopse.info/forum/ parsuje metafile pomocí Win API ve své PDF knihovně.
Embarcadero Technology Partner

RadekJanota

  • Host
Re:Převod JPG do RxRichEditu
« Odpověď #36 kdy: 15-01-2014, 15:27:30 »
Pokud by se někdo chtěl podívat (nebo to zkusit) na ty RTF a analyzovat proč jeden funguje a druhý ne, tak jsem je uložil zde:

https://drive.google.com/file/d/0B6FT6ZHCM3e9Sm1EeS1yZ3dkM2c/edit?usp=sharing

Jsou pojmenovány výstižně: Dobry.rtf, Spatny.rtf

Když do RXRichEdit načtu Dobry.rtf, tak mi jde měnit rozměr obrázku bez problémů, pokud načtu Spatny.rtf, tak se obrázek při změně pomrší.
Ještě doplním, že problém nastane POUZE pokud obrázek zmenšuji.

Jednoduchý test:

1) vytvořím nový projekt (dělám v XE3)
2) na form vložím RxRichEdit1
3)
RXRichEdit1.Lines.LoadFromFile('c:\TEMP\Dobry.rtf');
nebo
RXRichEdit1.Lines.LoadFromFile('c:\TEMP\Spatny.rtf');
4) změnit rozměr obrázku myší

Díky za jakýkoliv nápad nebo za test.