2 / 2 / 0
Регистрация: 11.10.2010
Сообщений: 35
1

Вставка изображения в RTF-файл

12.01.2012, 14:24. Показов 11466. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужно вставить BMP-шное изображение в конец или начало файла RTF.
Конкретного метода не нагуглил как это сделать, узнал только, что сам RTF понимает лишь EMF изображения. Конвертировать BMP в EMF не проблема, если это действительно так.

Подскажите пожалуйста, как вставить изображение в RTF файл?
Может быть есть в C++ Builder стандартные функции в RichEdit или нечто подобное? Мне не удалось найти, либо поправьте, плохо гуглил.

Очень жду ответа, спасибо большое!

Добавлено через 13 часов 27 минут
UP!
ну неужели никто не подскажет?..
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.01.2012, 14:24
Ответы с готовыми решениями:

Вставка изображения в файл Excel
у меня следующая проблема, необходимо вставить изображение в файл EXCEL, для этого я воспользовался...

RichTextBox и вставка кирилицы в RTF из буфера обмена
Всем привет. Попытался из SQL Server Management Studio скопировать запрос и вставить в свой...

Вставка закладки в шаблон формата RTF с последующей отгрузкой данного шаблона в richTextBox
Всем доброго дня. подскажите следующий момент. У меня есть шаблон файла формата RTF, в данном...

Создание rtf файла и запись в него текста и изображения
Доброго вам здоровичка!!! Помогите паж-ста с задачкой: На форме есть пикчербокс с фото, текстбокс...

9
LK
Заблокирован
12.01.2012, 15:03 2
C++
1
2
3
img = new TImage(RichEdit1);
img->Parent = RichEdit1;
img->Picture->LoadFromFile("C:\\test.bmp");
0
2 / 2 / 0
Регистрация: 11.10.2010
Сообщений: 35
12.01.2012, 21:29  [ТС] 3
Да, картинка добавляется, но когда сохраняю с РичБокса - документ пустой.
Моя задача на вход подать файл BMP, а на выходе получить RTF внутри с этой картинкой, вставленной в конец файла. Или можно просто в новосозданный файл RTF
0
LK
Заблокирован
12.01.2012, 21:43 4
стандартный RichEdit этого не умеет

Добавлено через 1 минуту
можно попытаться использовать компонент WordApplication c закладки MS Office, только предварительно надо в опциях-пакеты - отметить эти компоненты, по умолчанию они отключены из-за копирайтов
0
2 / 2 / 0
Регистрация: 11.10.2010
Сообщений: 35
12.01.2012, 22:04  [ТС] 5
Тоже не вариант, погуглил,

C++
1
WordApplication->Connect();// пытаемся связаться с Word
Надо чтобы был установлен на компе Word. Это не то, нужно, чтобы картинка в RTF впихивалась без привязки к столь громоздким библиотекам.

Если бы просто узнать алгоритм и как вообще хранятся файлы в rtf, я ничего не нагуглил подобного
Я бы просто втупую вставил бы по битикам картинку прямо в файл или в каком месте она там хранится. Но из RTF я лишь текст умею форматировать, а о картинках ничего нет.

Может еще варианты? кто что подскажет? Выкопировки кода?
буду очень благодарен


ЗЫ если же попытаюсь статически влинковать библиотеку Word'a, я могу только представить до каких размеров возрастет моя софтинка
0
LK
Заблокирован
12.01.2012, 22:14 6
погуглите про ричєдит версии 3

Добавлено через 6 минут
нашлось у меня такое
У меня TurboC++ никакого КвикРепорта или тому подобного нет.
Решил отчетики в RTF генерировать в ручтую.
В TStrings просто записываю {\\rtf1\\ansi\\ и т.д. и т.п.
Потом сохраняю с расширением rtf и все
В принципе вполне все сносно - и шрифт разного размера и таблички многострочные.
Все было хорошо до того момента пока не понадобилось вставлять картиночки.
Код нашел. Проверил. ВордПад открывает.
Но все оказалось не так то просто...
ВордПад единственный кто открывает.
Остальные программы (OO WordViewer Abiword и компоненты RichView, RichEdit) не хотят
Причем если ВордПадом пересохранить все открвают...

Вопрос во том как это починить?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
      TStrings *rtf = new TStringList();
      Graphics::TBitmap *BMP;
      BMP = new Graphics::TBitmap();
      BMP=Image4->Picture->Bitmap; //в ВМР картиночка
       
                          unsigned InfoHeaderSize = 0, ImageSize = 0;
                          AnsiString InfoHeader, Image;
                          AnsiString hexpict;
                          int I;
                          AnsiString mychar;
       
                          // GetDIBSizes, GetDIB из модуля Graphics
                          // Получаем размер заголовка и изображения цветной картинки
                          GetDIBSizes(BMP->Handle, InfoHeaderSize, ImageSize);
       
                          InfoHeader.SetLength(InfoHeaderSize);
                          Image.SetLength(ImageSize);
       
                          // Получаем сам заголовок и цветную картинку
                          GetDIB(BMP->Handle, BMP->Palette, &((InfoHeader.c_str())[0]), &((Image.c_str())[0]));
       
                          //Длина строки
                          hexpict.SetLength((InfoHeader.Length() + Image.Length()) * 2);
       
                          I = 1;
                          for (int z = 0; z < InfoHeader.Length(); z++){
                              mychar = IntToHex((int)((InfoHeader.c_str())[z]), 2);
       
                              if (mychar.Length() == 1) mychar = "0" + mychar;
       
                              mychar=mychar.SubString(mychar.Length()-1, 2);
       
                              (hexpict.c_str())[I - 1] = (mychar.c_str())[0];
                              (hexpict.c_str())[I] = (mychar.c_str())[1];
       
                              I=I+2;
                          }
                          for (int z = 0; z < Image.Length(); z++){
                              mychar = IntToHex((int)((Image.c_str())[z]), 2);
       
                              mychar=mychar.SubString(mychar.Length()-1, 2);
       
                              if (mychar.Length() == 1) mychar = "0" + mychar;
       
                              (hexpict.c_str())[I - 1] = (mychar.c_str())[0];
                              (hexpict.c_str())[I] = (mychar.c_str())[1];
       
                              I=I+2;
                          }
       
       
       
                          rtf->Add("{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fswiss\\fcharset204{\\*\\fname Arial;}Arial CYR;}{\\f1\\froman\\fprq2\\fcharset204{\\*\\fname Times New Roman;}Times New Roman CYR;}}");
                          rtf->Add("");      
       
                          //далее вставляю текст и т.д.
       
                          rtf->Add("{\\pict\\dibitmap "+hexpict+" }\\pard");
       
                          //далее снова вставляю текст и т.д.
       
                          rtf->Add("}");
       
                          rtf->SaveToFile("file.rtf");
То что я делаю в ручную dibitmap , то как сохраняет при пересохранении вордпад wmetafile8

В ручную {\pict \dibitmap ...... }
WopdPad {\pict\wmetafile8 ...... }
.... там и там разные

Причем уже смотрел The Rich Text Format (RTF) Specification
Вроде там dibitmap дозволенный формат...

Видимо дело в том, что версии как RTF, так и RichEdit могут быть разные. Не знаю как в TurboC, а например в BCB6 и Delphi7 юзается древнейший RichEdit 1.0 (riched32.dll), хотя уже в Win98 поддерживался 2.0 (riched20.dll), а в WinXP и вовсе 4.1 (msftedit.dll).
Разумеется в вордпаде юзается последняя версия, а в RichView\RichEdit возможно более древняя, не понимающая dibitmap в RTF

Дак в Турбе тоже что и в билдере 6 с Richedit
Я уже с этим встречался.
Чтоб таблички отображать красиво надо подключать с программой RICHED20.DLL таскать.
А есть из 2003 офиса вытащит этот RICHED20.DLL дак даже мышкой можно ширину столбиков таблицы менять - круче ВордПада из ХР
Плюс Юникод открывает Richedit тоже как хочет (в зависимости от 9х или 2000/XP).

А с RTF вообще беда какаято
Спецификация это одно а как оно обрабатывается разными программами это другое...
Скачал
http://www.trichview.com/rvfiles/rvedit.zip
Сделал минималистические rtf с картинками.
Оказалось что у меня тега \plain перед текстом не хватает

Но все равно если BMP по вышепредеденному коду, то
чтобы Ворд вьювер понимал надо таким образом обозначать
\par {\pict\dibitmap0\wbmwidthbytes52\picw103\pich36\picwgoal1545\pichgoal540
Этой программе http://www.trichview.com/rvfiles/rvedit.zip
хватает и
\par {\pict\dibitmap0
Ворд-паду вообще хоть как и без \plain можно.
А ОпенОфис и Абиворд картинку не видит

А вот если конвертнуть BMP в EMF - все утро придумывал Ж)
и вставить как
\par {\pict\emfblip\picw3219\pich1125\picwgoal1545\pichgoal545
то тут Ворд-Пад не видит, зато все остальные видят

Может кому пригодится простейший код BMP -> EMF для RTF ниже, примеры RTF прикрепил
ЗЫ: Что-то идея генерировать RTF разонравилась.. буду пробывать подключать freereport к этой ТурбеС++

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
         Graphics::TBitmap *BMP = new Graphics::TBitmap();
         TMetafile *MF = new TMetafile();
         TMetafileCanvas *MFCanvas;
         BMP->LoadFromFile("default.bmp");
         MF->Height = BMP->Height;
         MF->Width = BMP->Width;
         try{
          MFCanvas=new TMetafileCanvas(MF, 0);
       
          MFCanvas->Draw(0, 0, BMP);
       
          delete MFCanvas;
       
          //MF->SaveToFile("default.emf");
         }catch( ... ){
          delete MFCanvas;
         }
         delete BMP;
       
         AnsiString hexpict;
         TMemoryStream *ST=new TMemoryStream;
         MF->SaveToStream(ST);
         delete MF;
         ST->Position=0;
         hexpict.SetLength(ST->Size*2);
         int ptr;
         AnsiString mychar;
         int I=1;
         for (int i = 0; i <ST->Size; i++) {
           ST->Read(&ptr,1);
           mychar=IntToHex((int) ptr, 2);
              if (mychar.Length() == 1) mychar = "0" + mychar;
       
              mychar=mychar.SubString(mychar.Length()-1, 2);
       
              (hexpict.c_str())[I - 1] = (mychar.c_str())[0];
            (hexpict.c_str())[I] = (mychar.c_str())[1];
            I=I+2;
         }
              TStrings *sfile = new TStringList();
       
              sfile->Add("{\\rtf1");
              sfile->Add("\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fswiss\\fcharset204{\\*\\fname Arial;}Arial CYR;}{\\f1\\froman\\fprq2\\fcharset204{\\*\\fname Times New Roman;}Times New Roman CYR;}}");
       
            sfile->Add("\\pard\\qc\\b\\fs28Ура\\fs16\\b0\\par");
       
              sfile->Add("{\\pict\\emfblip "+hexpict+" }\\pard");
       
            sfile->Add("\\pard\\qc\\b\\fs28Ура\\fs16\\b0\\par");
              sfile->Add("}");
            sfile->SaveToFile("zz.rtf");
код не мой, не проверял
1
2 / 2 / 0
Регистрация: 11.10.2010
Сообщений: 35
19.01.2012, 02:30  [ТС] 7
Гениально!!
Все прекрасно работает!
Спасибо большое!
0
UeArtemis
18 / 18 / 3
Регистрация: 23.09.2011
Сообщений: 205
17.06.2016, 14:57 8
У меня почему-то остаётся метафайл пустой. Сохранял отдельно - 0 байт.

Добавлено через 4 часа 33 минуты
С метафайлом помогли разобраться. Удалять метаканву нужно перед загрузкой в поток.
А вот, что эта часть кода у Вас значит?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
         int ptr;
         AnsiString mychar;
         int I=1;
         for (int i = 0; i <ST->Size; i++) {
           ST->Read(&ptr,1);
           mychar=IntToHex((int) ptr, 2);
              if (mychar.Length() == 1) mychar = "0" + mychar;
       
              mychar=mychar.SubString(mychar.Length()-1, 2);
       
              (hexpict.c_str())[I - 1] = (mychar.c_str())[0];
            (hexpict.c_str())[I] = (mychar.c_str())[1];
            I=I+2;
         }
Зачем проверка на длину, если в IntToHex задаёте вывод в 2 символа?
Ну, и следующая строчка кажется абсурдной. Зачем брать подстроку в 2 символа с конца, если, по идее, их всего 2?
И потом посимвольно последовательно присваивать первый символ к первому, второй к второму. Не понимаю.
Не будет ли равноценным этот более простой код? Или я что-то упустил?
C++
1
2
3
4
5
6
        int tBt;
        for(int i=0; i<ST->Size; i++)
        {
            ST->Read(&tBt,1);
            hexpict+=IntToHex(tBt,2);
        }
Добавлено через 16 часов 31 минуту
Комбинация тегов {\pict\dibitmap0\wbmwidthbytes52\picw103\pich36\picwgoal1545\pichgoal540 из файла BMP2 отображается у меня во всех редакторах корректно. Остальные - где-то есть картинка, а где-то нет.

Добавлено через 2 минуты
Но {\pict\wmetafile8\picwgoal810\pichgoal1200, думаю, надёжнее.

Добавлено через 1 час 26 минут
Только BYTE tBt, естественно.

Добавлено через 1 час 49 минут
Я так понимаю, дело в кодировке. Метафайл, который отображается и в WordPad'е и в MS Word'e, при той же картине внутри имеет другой код.
Заметил, что генерируемый мною текст кода начинается с 010000006C..., а тот, что сохраняется текстовыми процессорами - 010009...
Кто знает, где про структуру метафайлов почитать можно?

Добавлено через 42 минуты
Так, от тестовых редакторов шапка перед моим кодом:
010009000003c607000008003c05000000003c05000026060f006e0a574d464301000000000001
00952300000000010000004c0a0000000000004c0a0000

Ещё хвост отличается, но я там не нащупал стык пока.

Добавлено через 2 часа 0 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        //В метафайл
        TMetafile *MF = new TMetafile();
        MF->Inch=MyForm1->PixelsPerInch;
        MF->MMWidth=254*ImageFon->Picture->Width/MF->Inch;
        MF->MMHeight=254*ImageFon->Picture->Height/MF->Inch;
        MF->SetSize(ImageFon->Width*1.1,
                    ImageFon->Height*1.1);
        //Рисуем
        TMetafileCanvas *tMetaCanv = new TMetafileCanvas(MF,0);
        tMetaCanv->Draw(0,0,ImageFon->Picture->Bitmap);
        delete tMetaCanv;//Удалять до загрузки в поток/файл!
        MF->SaveToFile("tmp_test.emf");
        //Получаем байты
        int KolB=GetEnhMetaFileBits((HENHMETAFILE)MF->Handle, 0, NULL);
        BYTE *tBuffer = new BYTE[KolB];
        GetEnhMetaFileBits((HENHMETAFILE)MF->Handle, KolB, tBuffer);
        //В строку
        AnsiString hexpict("");
        for(int i=0; i<KolB; i++)
        {
            hexpict+=IntToHex(tBuffer[i],2);
        }
        //Вывод
        TMP+="\\pard\\par{\\pict\n";
        TMP+=("\\picw"+IntToStr(MF->Width)+"\n");
        TMP+=("\\pich"+IntToStr(MF->Height)+"\n");
        TMP+=("\\picwgoal"+IntToStr(1440*MF->Width/MF->Inch)+"\n");
        TMP+=("\\pichgoal"+IntToStr(1440*MF->Height/MF->Inch)+"\n");
        TMP+=("\\wmetafile8\n"+hexpict+"}\\pard\\par\\par\n");//emfblip
        //Чистим
        delete [] tBuffer;
        delete MF;
TMP тут AnsiString, которую потом сохраним в rtf-файл.
Видит картинку в Word'е, а вот в WordPad нет, как и в RichEdit с поддержкой OLE.
Проблема в структуре метафайла, т.к. другие метафайлы видят все.
Надеюсь, у кого-нибудь будут соображения по этой теме.
0
UeArtemis
18 / 18 / 3
Регистрация: 23.09.2011
Сообщений: 205
21.06.2016, 13:20 9
Хвост тоже нащупал!

0400000003010800050000000b0200000000050000000c02570157010500000014020000000007
000000fc020000ffffff000000040000002d010000050000000102ffffff000400000002010200
040000002d0100000c00000040092100f0000000000000005a015a0100000000040000002d0100
0008000000fa0200000100000080808000040000002d0101000400000004010d00070000001804
4b014b010f000f0008000000fa0200000000000000000000040000002d01020008000000fa0200
0001000000c0c0c000040000002d0103000400000004010d000700000018041701170143004300
070000001804e200e200780078000500000014025e003601050000001302fc0024000500000014
022400fc0005000000130236015e000500000014020f00ad000500000013024b01ad0005000000
140224005e000500000013023601fc000500000014025e002400050000001302fc003601040000
002d01020004000000f0010300050000001402ad000f00040000002d0101000400000004010d00
050000001302ad004b010500000014020f00ad000500000013024b01ad001c000000fb02f5ff00
0000000000900100000001000000005461686f6d6100003f4700003f3f00006937213f3f123f3f
3f123f3f3f613f12040000002d010300050000000902808080000a000000320aa8004e01020000
0030b006000500050000001402a80059010c000000320a0100a800030000003930b00006000600
05000500000014020100b9000d000000320a4b01a300040000002d3930b0040006000600050005
00000014024b01b8000d000000320aa800010004000000313830b0060006000600050005000000
1402a8001800040000002d01020007000000fc020100000000000000040000002d0104001c0000
00fb021000070000000000bc02000000cc0102022253797374656d000000000000000000000000
0000000000000000000000000000040000002d010500050000001402ad00ad0008000000fa0200
000200000080000000040000002d0106000400000004010d0007000000fc020000800000000000
040000002d01070005000000010280000000040000000201020005000000130236005500040000
002d01020004000000f001060008000000fa0200000100000080000000040000002d0106000400
000004010d000a000000240303005e003b005700400055003600040000002d01040004000000f0
010700040000002d01030005000000090280000000040000002d010400050000000102000000ff
040000000201010009000000320a270055000100000055bb070005000000140227005c00040000
002d01020004000000f0010600040000002d010400040000002d010500050000001402ad00ad00
08000000fa0200000200000000008000040000002d0106000400000004010d0007000000fc0200
00000080000000040000002d010700050000000102000080000400000002010200050000001302
b4005800040000002d01020004000000f001060008000000fa0200000100000000008000040000
002d0106000400000004010d000a000000240303006100af006200b7005800b400040000002d01
040004000000f0010700040000002d01030005000000090200008000040000002d010400050000
000102000000ff040000000201010009000000320ab40058000100000049bb0400050000001402
b4005c00040000002d010200040000002d010400040000002d010500030000000000

Вот что это за "оболочка" для моего файла? Универсальная ли она?

Добавлено через 3 часа 39 минут
The Windows GDI API provides a way to save and load metafiles on disk. This is the CreateMetafile(LPCTSTR filePath) function. But, using it for these purposes not a good idea. This way, a created metafile doesn't work with all versions of MS Word and Picture object (IPicture). To avoid these restrictions, you need to save the metafile in a placeable format. In this case, metafile bits are prefixed with a metafile header structure. This structure contains the metafile dimensions and an indication of the placeable metafile. Its size is 22 bytes. The structure is not defined in standard header files; thus, you need to define it explicitly. The next lines of code show how to use the WMFile class to save a placeable metafile. This part of the code can be used in conjunction with the previous one.

C++
1
2
3
    WMFile wmfFile(metafile, extents.cx, extents.cy, FALSE);
    LPCTSTR filename = _T("test.wmf");
    wmfFile.save(fileName);
О, нужно копать в этом направлении.
0
UeArtemis
18 / 18 / 3
Регистрация: 23.09.2011
Сообщений: 205
12.06.2017, 10:54 10
Это может быть EMF+? Как конвертировать EMF в EMF+?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.06.2017, 10:54
Помогаю со студенческими работами здесь

Что-то типа OLE- объекта для вставки с помощью АСПа например файл *.rtf или *.doc в ASP-файл
Реально надо заделать что-то типа OLE- объекта для вставки с помощью АСПа например файл *.rtf или...

Загрузить RTF файл
Всем привет, у меня вопрос, как вывести в делфи в какой нибудь компонент RTF файл с картинками?И...

Как записывать в rtf файл
Пожалуйста, можно пример кода как записывать в rtf файл, или как работать с ним, за ранее спасибо

Как экспортировать в rtf файл
Мне нужно экспортировать в rtf из результатов форм с JPanel. Какие jar файлы предназначены для...

Вставка изображения
Здравствуйте. Задача в следующем: при вставке ссылки на картинку в комментарии необходимо...

Вставка изображения
Никак не могу разобраться как вставлять изображение в текст. &lt;img scr=&quot;images/1.png&quot;&gt; не работает.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru