0

PDF 内のすべての画像を抽出し、それらを DIB 形式に変換しようとしています。最初の部分は簡単です。PDF のすべてのコンテンツを抽出し、それらを反復処理して、PDEImage を見つけるたびに、それらを配列に入れます。

しかし、私は2番目の部分をどのように進めるかについてはわかりません。すべての AVConversion メソッドを使用すると、画像だけでなく PDF のページ全体を他の形式に変換できるようです。

このタスクを達成する方法はありますか? 前もって感謝します!

編集:問題をさらに詳しく説明します。

Visual C++ と .NET Framework 4 を使用して Adob​​e Acrobat プラグインを作成しています。

プラグインの目的は、(とりわけ) PDF ファイルから画像データを抽出し、それらのデータを DIB に変換することです。DIS に変換する必要があるのは、それらの DIB を別のライブラリに渡して、画像の修正作業を行うためです。

今私の問題は、PDFの画像データをDIBに変換することです。PDF 上の画像データは、明らかに画像のすべてのカラー データを含む PDEImage (参照リンク) と呼ばれる形式で見つかります。ここで、次のコードを使用して、画像から上記の画像データ ビットを抽出し、CreateCompatibleBitmap() および SetBitmapBits() で使用して HBITMAP ハンドルを取得しています。次に、それを他の必要なパラメーターと共に GetDIBits() に渡し、MSDN に記載されているバイト配列の形式で DIB を取得します。

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 を取得し、次に CreateCompatibleBitmap() を使用して DDB を作成し、次に SetBitmapBits() を使用して実際のデータを DDB に設定します。あれは正しいですか?

  2. BITMAPINFO 構造体の作成方法に問題はありますか。私は、最終的に取得する DIB の形式に関するすべての詳細を含める必要があると想定しています。

  3. GetDIBits() を呼び出したときに、ビットマップ データを DIB としてバフに取得できないのはなぜですか?

4

1 に答える 1

0

PDFファイルの内部構造にアクセスするために使用するライブラリはわかりませんが、目前の問題にはツリーごとに異なるサブ問題があります。

  1. PDFファイル内のすべての画像を検索
  2. 画像をコンポーネントにデコードします
  3. デコードされた画像をDIBに変換します

すべての画像を検索

画像は、コンテンツストリーム内、または辞書に添付されたストリームで発生する可能性があります。コンテンツストリーム内のすべての画像を検索するには、Pages、XObjects、またはPatternsのいずれかですべてのコンテンツストリームを検索する必要があります。それらのそれぞれは、すべてのXObjectを参照するResources-> XObjectディクショナリを持つことができます(XObjectはImageにすることができます)。

インライン画像を避けた場合は、PDFファイルをスキャンするだけで、XObjectサブタイプImageタイプの各ディクショナリをデコードできます。

デコード

PDFファイル内の個別のオブジェクトのすべてのストリーム(コンテンツストリーム内のインライン)はエンコードされており、デコード配列を使用した後処理が必要です。デコードのために実行できる必要があるいくつかのフィルターがあります。Flateデコード(ZLIB)、JPEG、およびCCITT(fax G3 / G4)は、おそらく画像に最もよく使用されます。うまくいけば、使用するPDFライブラリがストリームをデコードする方法を知っているでしょう。

次に、各色成分を入力値から出力値にスケーリングできるデコード配列(少しまれです)があります。これは線形変換です。

DIBへ

次の行は、デコードされた画像のDIBへの変換です。つまり、カラーコンポーネントをWindowsが「取得」できるものに変換する必要があります(たとえば、パレット、RGBのグレースケール(特別なパレット)。PDFは非常に多様な色空間をサポートしており、RGBに変換するのは簡単ではありません。ここで、処理する必要のあるPDFが選択したサブセット(RGBやパレットなど)のみを使用することを願っています。これで、ビットマップヘッダー(BITMAPINFO)を作成し、すべてのデータを入力して、DIB作成関数CreateDIBSectionを呼び出してDIBを簡単に作成できます。アプリケーションが必要とする方法でDIBを処理します。

エピローグ

全体として:すべてのPDFファイルを処理し、すべての画像を見つけることができるようにすることは、非常に困難な作業です。PDFが常にDeviceRGB形式であり、常にJPEGなどであり、コンテンツストリームにインライン化されていないことがわかっている場合、ソースを制御します。それは実行可能です。

于 2012-03-04T20:10:55.880 に答える