Конвертировать данные изображения (PDEImage) в PDF в DIB с помощью C ++? - PullRequest
0 голосов
/ 23 февраля 2012

Я пытаюсь извлечь все изображения в формате PDF, а затем преобразовать их в формат DIB. Первая часть проста. Я извлекаю все содержимое в PDF, затем перебираю их, и всякий раз, когда я нахожу PDEImage, я помещаю их в массив.

Но я не представляю, что делать со второй частью. Похоже, что все методы AVConversion позволяют конвертировать целую страницу PDF, а не только изображения, в другие форматы.

Есть ли способ, которым я могу выполнить эту задачу? Заранее спасибо!

РЕДАКТИРОВАТЬ: дальнейшая разработка проблемы.

Я пишу плагин Adobe Acrobat с использованием Visual C ++ с .NET Framework 4.

Назначение плагина состоит в том, чтобы (помимо прочего) извлечь данные изображения из файла PDF, а затем преобразовать эти данные в DIB. Необходимость преобразования в DIS заключается в том, что я затем передаю эти DIB в другую библиотеку, которая выполняет на них некоторую коррекцию изображения.

Теперь моя проблема заключается в преобразовании указанных данных изображения в PDF-файлах в DIB. Данные изображения в PDF-файлах находятся в формате PDEImage (Ref Link), где, по-видимому, они содержат все данные о цвете изображения. Теперь я использую следующий код для извлечения указанных битов данных изображения из изображения, которое будет использоваться с CreateCompatibleBitmap () и SetBitmapBits () для получения дескриптора HBITMAP. Затем я передаю это вместе с другими необходимыми параметрами в GetDIBits (), чтобы получить DIB в виде байтового массива, как указано в MSDN.

void GetDIBImage(PDEElement element)
{
    //Obtaining a PDEImage
    PDEImage image;
    memset(&image, 0, sizeof(PDEImage));
    image = (PDEImage)element;

    //Obtaining attributes (such as width, height)
    //of the image for later use
    PDEImageAttrs attrs;
    memset(&attrs, 0, sizeof(attrs));
    PDEImageGetAttrs(image, &attrs, sizeof(attrs));

    //Obtainig image data from PDEImage to a byte array
    ASInt32 len = PDEImageGetDataLen(image);
    byte *data = (byte *)malloc(len);
    PDEImageGetData(image, 0, data);

    //Creating a DDB using said data
    HDC hdc = CreateCompatibleDC(NULL); 
    HBITMAP hBmp = CreateCompatibleBitmap(hdc, attrs.width, attrs.height);  
    LONG bitsSet = SetBitmapBits(hBmp, len, data);  //Here bitsSet gets a value of 59000 which is close to the image's actual size

    //Buffer which GetDIBits() will fill with DIB data
    unsigned char* buff = new unsigned char[len];

    //BITMAPINFO stucture to be passed to GetDIBits()
    BITMAPINFO bmpInfo;
    memset(&bmpInfo, 0, sizeof(bmpInfo));

    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = (LONG)attrs.width;
    bmpInfo.bmiHeader.biHeight = (LONG)attrs.height;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 8;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = ((((bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biBitCount) + 31) & ~31) >> 3) * bmpInfo.bmiHeader.biHeight;  
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;

    //Callling GetDIBits()
    //Here scanLines get a value of 0, while buff receives no data.
    int scanLines = GetDIBits(hdc, hBmp, 0, attrs.height, &buff, &bmpInfo, DIB_RGB_COLORS);

    if(scanLines > 0)
    {
        MessageBox(NULL, L"SUCCESS", L"Message", MB_OK);
    }
    else
    {
        MessageBox(NULL, L"FAIL", L"Message", MB_OK);
    }
}

Вот мои вопросы / проблемы.

  1. Правильно ли я использую функции CreateCompatibleDC (), CreateCompatibleBitmap () и SetBitmapBits ()? Я думаю, что я использую CreateCompatibleDC () для получения текущего DC, затем создаю DDB с помощью CreateCompatibleBitmap () и затем устанавливаю фактические данные в DDB с помощью SetBitmapBits (). Это правильно?

  2. Есть ли проблема с тем, как я создал структуру BITMAPINFO. Я предполагаю, что он должен содержать все детали относительно формата DIB, который я в конечном итоге получу.

  3. Почему я не получаю растровые данные в виде DIB в бафф, когда я вызываю GetDIBits ()?

1 Ответ

0 голосов
/ 05 марта 2012

Я не знаю, какую библиотеку вы используете для доступа к внутренним структурам PDF-файла, но у рассматриваемой проблемы будут различные подзадачи:

  1. Найти все изображения в файле PDF
  2. Декодировать изображения на их составляющие
  3. Преобразование декодированного изображения в DIB

Найти все изображения

Изображения могут появляться в потоках контента или в потоках, прикрепленных к словарям. Чтобы найти все изображения в потоках контента, вам нужно найти все потоки контента в страницах, XObjects или в шаблонах. Каждый из них может иметь словарь ресурсов -> XObject, который ссылается на все объекты XObject (а XObject может быть изображением).

Если вы избегаете встроенных изображений, вы можете просто отсканировать файл PDF, и каждый неконтролируемый тип изображения XObject может быть декодирован.

Decode

Все потоки (встроенные в потоки контента) в отдельных объектах в файле PDF кодируются и должны быть постобработаны с использованием массивов декодирования. Есть несколько фильтров, которые вы должны быть в состоянии выполнить для декодирования. Флат-декодирование (ZLIB), JPEG и CCITT (факс G3 / G4), вероятно, наиболее часто используются для изображений. Надеюсь, используемая вами библиотека PDF будет знать, как декодировать потоки ..

Далее идут массивы декодирования (немного редко), в которых каждый компонент цвета можно масштабировать от входного значения до выходного значения. Это линейное преобразование.

до DIB

Следующим по очереди является преобразование декодированного изображения в DIB. Это означает, что вам нужно преобразовать цветовые компоненты в то, что Windows может «получить» (например, «Палитра», «Оттенки серого» (специальная палитра) в RGB. PDF поддерживает очень большое разнообразие цветовых пространств, и преобразование их в RGB не является синекурой. Мы надеемся, что PDF-файлы, которые вам нужно обработать, используют только подмножество выбора (например, RGB и палитру). Теперь можно просто создать DIB, создав заголовок растрового изображения (BITMAPINFO), заполнить все данные и вызвать функцию создания DIB CreateDIBSection и они обрабатывают DIB так, как нужно вашему приложению.

Эпилог

В целом: иметь возможность обрабатывать все файлы PDF и находить все изображения - довольно сложная задача, если вы контролируете источник, если PDF-файлы и вы знаете, что они всегда в формате DeviceRGB и всегда JPEG и т. Д. И никогда не вставляются в поток контента это выполнимо.

...