Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Системное программирование и WinAPI > BMP to RTF


Автор: Betelgeuse 19.07.23, 05:40
Пишу самодельный эл.управления типа RichTextBox для вывода результатов программы. RichTextBox не устраивает, потому что нужны разделения на страницы и миниатюры страниц как в pdf- или djvu- просмотрщиках.
Появилась задача вставить картинки, кроме текста. Делаю на чистом WinAPI без MFC и др. Само рисование не вызывает вопросов. Проблема в следующем, чтобы выделить и скопировать, а потом вставить текст с картинками в Word, нужно перевести эти текст и картинки в формат RTF. Интересует перевод именно рисунков в RTF.

По теме найдено
1) из Delphi Russian Knowledge Base 3, благодоря проделанной работе Vit-a
Скрытый текст

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    function BitmapToRTF(pict: TBitmap): string;
     
    var
     
    bi, bb, rtf: string;
     
    bis, bbs: Cardinal;
     
    achar: ShortString;
     
    hexpict: string;
     
    I: Integer;
     
    begin
     
    GetDIBSizes(pict.Handle, bis, bbs);
     
    SetLength(bi, bis);
     
    SetLength(bb, bbs);
     
    GetDIB(pict.Handle, pict.Palette, PChar(bi)^, PChar(bb)^);
     
    rtf := '{\rtf1 {\pict\dibitmap0 ';
     
    SetLength(hexpict, (Length(bb) + Length(bi)) * 2);
     
    I := 2;
     
    for bis := 1 to Length(bi) do
     
    begin
     
       achar := IntToHex(Integer(bi[bis]), 2);
     
       hexpict[I - 1] := achar[1];
     
       hexpict[I] := achar[2];
     
       Inc(I, 2);
     
    end;
     
    for bbs := 1 to Length(bb) do
     
    begin
     
       achar := IntToHex(Integer(bb[bbs]), 2);
     
       hexpict[I - 1] := achar[1];
     
       hexpict[I] := achar[2];
     
       Inc(I, 2);
     
    end;
     
    rtf := rtf + hexpict + ' }}';
     
    Result := rtf;
     
    end;

Но для меня здесь проблема в функциях из VCL (GetDIBSizes, GetDIB) их переводе на Си.

2) Нашел по адресу microsoft.public.pocketpc.developer.narkive.com
Скрытый текст

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    PBITMAPINFO pbmi = NULL;
    WORD cClrBits = 1;
    int nColors = 2;
    RGBQUAD Colors2[] =
    {
    {0x00, 0x00, 0x00, 0x00},
    {0xFF, 0xFF, 0xFF, 0x00}
    };
     
    int nBytesPerLine = ((nWidth * cClrBits + 31)&(~31)) / 8;
    DWORD dwBitmapInfoSize = sizeof(BITMAPINFOHEADER) + nColors * sizeof
    (RGBQUAD);
    DWORD dwFileHeaderSize = dwBitmapInfoSize + sizeof(BITMAPFILEHEADER);
    HBITMAP hBmp;
    LPVOID ppvBits;
    BYTE *lpBits, *lpBuf = new BYTE[dwBitmapInfoSize + 1];
    BITMAPINFO* lpbi = (BITMAPINFO*) lpBuf;
    BITMAPFILEHEADER bmpfhdr;
    BITMAPINFOHEADER& bih = lpbi->bmiHeader;
     
    // Initialize the fields in the BITMAPINFO structure.
    memset(&bih, 0, sizeof(BITMAPINFOHEADER));
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = nWidth;
    bih.biHeight = nHeight;
    bih.biPlanes = 1;
    bih.biBitCount = 1;
    bih.biCompression = BI_RGB;
    bih.biSizeImage = 0;
     
    RGBQUAD* pColors = &Colors2[0];
    memcpy(&lpbi->bmiColors[0], &pColors[0], sizeof(RGBQUAD));
    memcpy(&lpbi->bmiColors[1], &pColors[1], sizeof(RGBQUAD));
     
    bmpfhdr.bfType = 0x4d42; //'BM' file type
    bmpfhdr.bfSize = dwFileHeaderSize + (nBytesPerLine * nHeight);
    bmpfhdr.bfReserved1 = 0;
    bmpfhdr.bfReserved2 = 0;
    bmpfhdr.bfOffBits = dwFileHeaderSize;
     
    // Then create our DIBSection using the structure manually created
    from above...
    HBITMAP hPictureBMP = CreateDIBSection(pictureDC, lpbi,
    DIB_RGB_COLORS, &ppvBits, NULL, 0);
    lpBits = (BYTE*)ppvBits;
    HDC hMemDC = CreateCompatibleDC(pictureDC);
     
    hBmp = (HBITMAP) SelectObject(hMemDC, hPictureBMP);
    BitBlt(hMemDC,0,0,nWidth,nHeight,pictureDC,0,0,SRCCOPY);
    SelectObject(hMemDC, hBmp);
    DeleteObject(hPictureBMP);
     
    DWORD dwNumBytes;
     
    if (ppvBits)
    {
    char szBuffer[MAX_BUFFER];
     
    // pichgoal = 1440 / DPI = 1440 / 96 = 15
    int rtfHeaderSize = sprintf(szBuffer,"{\\pict\\dibitmap0\
    \wbmbitspixel%u\\wbmplanes%u\\wbmwidthbytes%u\\picw%u\\pich%u\\picwgoal
    %u\\pichgoal%u\\picscalex100\\picscaley100 ", bih.biBitCount,
    bih.biPlanes, nBytesPerLine, nWidth, nHeight, nWidth*16, nHeight*16);
    {
    int offset;
    for (offset=0; offset < (int)dwBitmapInfoSize; offset++)
    sprintf(szBuffer+rtfHeaderSize+offset*2,"%02X",lpBuf[offset]);
    for (offset=0; offset<nBytesPerLine * nHeight; ++offset)
    sprintf(szBuffer+rtfHeaderSize+(dwBitmapInfoSize+offset)
    *2,"%02X",lpBits[offset]);
    }
    szBuffer[rtfHeaderSize + (dwBitmapInfoSize + nBytesPerLine *
    nHeight) * 2] = '}';
    szBuffer[rtfHeaderSize + (dwBitmapInfoSize + nBytesPerLine *
    nHeight) * 2 + 1] = 0;
     
    // Insert bitmap into document (there is enough rooom!!)
    memmove(documentSignature + strlen(szBuffer), documentSignature,
    strlen(documentSignature) + 1);
    memcpy (documentSignature, szBuffer, strlen(szBuffer));
    }
    delete[] lpBuf;
    DeleteObject(hBmp);
    DeleteDC(hMemDC);


Этот код взял за основу, переделываю под свою задачу.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    void ReportPicturesToRTF()
    {
        int i;
        int w, h, ncolors, nbytesperline, rtfheadersize;
        char buffer[256];
        HDC picturedc, hmemdc;
        HBITMAP hbmp, hpicturebmp;
        PBITMAPINFO pbmi;
        LPVOID ppvbits;
        BITMAPFILEHEADER bmpfhdr;
        WORD clrbits;
        DWORD dwbitmapinfosize, dwfileheadersize;
        BYTE *lpbits, *lpbuf;
        BITMAPINFO *lpbi;
        RGBQUAD* pcolors;
        RGBQUAD colors2[] =
        {
            {0x00, 0x00, 0x00, 0x00},
            {0xFF, 0xFF, 0xFF, 0x00}
        };
        picturedc = GetDC(e::reporthwnd[3]); // <--- здесь я беру окно со свои рисунком
        pbmi = NULL;
        clrbits = 1;
        ncolors = 2;
        w = 100;
        h = 20;
        nbytesperline = ((w * clrbits + 31) & (~31)) / 8;
        dwbitmapinfosize = sizeof(BITMAPINFOHEADER) + ncolors * sizeof(RGBQUAD);
        dwfileheadersize = dwbitmapinfosize + sizeof(BITMAPFILEHEADER);
        lpbuf = new BYTE[dwbitmapinfosize + 1];
        lpbi = (BITMAPINFO*) lpbuf;
        BITMAPINFOHEADER& bih = lpbi->bmiHeader;
        memset(&bih, 0, sizeof(BITMAPINFOHEADER));
        bih.biSize = sizeof(BITMAPINFOHEADER);
        bih.biWidth = w;
        bih.biHeight = h;
        bih.biPlanes = 1;
        bih.biBitCount = 1;
        bih.biCompression = BI_RGB;
        bih.biSizeImage = 0;
        pcolors = &colors2[0];
        memcpy(&lpbi->bmiColors[0], &pcolors[0], sizeof(RGBQUAD));
        memcpy(&lpbi->bmiColors[1], &pcolors[1], sizeof(RGBQUAD));
        bmpfhdr.bfType = 0x4d42;
        bmpfhdr.bfSize = dwfileheadersize + (nbytesperline * h);
        bmpfhdr.bfReserved1 = 0;
        bmpfhdr.bfReserved2 = 0;
        bmpfhdr.bfOffBits = dwfileheadersize;
        hpicturebmp = CreateDIBSection(picturedc, lpbi, DIB_RGB_COLORS, &ppvbits, NULL, 0);
        lpbits = (BYTE*)ppvbits;
        hmemdc = CreateCompatibleDC(picturedc);
        hbmp = (HBITMAP) SelectObject(hmemdc, hpicturebmp);
        BitBlt(hmemdc, 0, 0, w, h, picturedc, 0, 0, SRCCOPY);
        SelectObject(hmemdc, hbmp);
        if (ppvbits)
        {
            rtfheadersize = sprintf(buffer,"{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes%u\\wbmwidthbytes%u\\picw%u\\pich%u\\picwgoal%u\\pichgoal%u\\picscalex100\\picscaley100 ", bih.biBitCount,bih.biPlanes, nbytesperline, w, h, w*16, h*16);
            {
                for (i=0; i<((int)dwbitmapinfosize); i++)
                {
                    sprintf(buffer + rtfheadersize+i * 2, "%02X", lpbuf[i]);
                }
                for (i=0; i<(nbytesperline*h); ++i)
                {
                    sprintf(buffer + rtfheadersize + (dwbitmapinfosize + i) * 2, "%02X", lpbits[i]);
                }
            }
            buffer[rtfheadersize + (dwbitmapinfosize + nbytesperline * h) * 2] = '}';
            buffer[rtfheadersize + (dwbitmapinfosize + nbytesperline * h) * 2 + 1] = 0;
     
            // Insert bitmap into document (there is enough rooom!!)
            //memmove(documentSignature + strlen(buffer), documentSignature, strlen(documentSignature) + 1);
            //memcpy (documentSignature, buffer, strlen(buffer));
        }
        delete[] lpbuf;
        DeleteObject(hpicturebmp);
        DeleteObject(hbmp);
        DeleteDC(hmemdc);
    }

Вопросы:
1. Здесь, как я понял, для 2-х цветных (черно-белых) BMP. А как быть с большим количеством цветности ? Хотелось бы как минимум 256.
2. Есть ли уже готовые решения для такой задачи ?

Автор: B.V. 20.07.23, 13:12
Цитата Betelgeuse @
2. Есть ли уже готовые решения для такой задачи ?

Не подобное ли ты ищешь?

Автор: Betelgeuse 20.07.23, 13:36
Цитата B.V. @
Не подобное ли ты ищешь?

Не похоже,
Там судя по названиям OLE технология используется. И нигде в HEX-значения перевода нет

А мне нужно
1) мой hDC перегнать в HBITMAP
2) из HBITMAP выудить всю эту информацию (заголовки, размеры, цвета)
3) с учетом этой информации записать в СТРОКУ область данных рисунка HEX-значения
4) Потом эту СТРОКУ можно будет скопировать в буфер обмена.

Застрял на изучении формата BMP (такая муть!)
Сейчас сочиняю на Си функцию из VCL которая там имеет название GetDIBSizes()...

PS думал за день справлюсь - ошибался ))

Автор: Betelgeuse 21.07.23, 06:00
B.V.Спасибо за наводку на сайт, www.codeproject.com
Я про него как-то забыл )) надо там внимательнее поискать.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)