我正在尝试提取PDF中的所有图像,然后将它们转换为DIB格式。第一部分很简单。我提取PDF中的所有内容,然后遍历它们,每当我找到PDEImage时,我将它们放在一个数组中。
但我对如何处理第二部分毫无头绪。看起来所有AVConversion方法都允许您将PDF的整页(而不仅仅是图像)转换为其他格式。
我有什么方法可以完成这项任务吗?提前谢谢!
编辑:进一步阐述问题。
我正在使用Visual C ++和.NET Framework 4编写Adobe Acrobat插件。
插件的目的是(除其他外)从PDF文件中提取图像数据,然后将这些数据转换为DIB。转换为DIS的需要是因为我然后将这些DIB传递给另一个库,它们对它们进行了一些图像校正工作。
现在我的问题是将PDF中的所述图像数据转换为DIB。 PDF上的图像数据以称为PDEImage(Ref Link)的格式找到,显然它包含图像的所有颜色数据。现在我使用以下代码从要与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);
}
}
以下是我的问题/疑虑。
我使用CreateCompatibleDC(),CreateCompatibleBitmap()和SetBitmapBits()函数的方式是否正确?我的想法是我使用CreateCompatibleDC()获取当前DC,然后使用CreateCompatibleBitmap()创建DDB,然后使用SetBitmapBits()将实际数据设置为DDB。这是对的吗?
我创建BITMAPINFO结构的方式是否有问题。我假设它需要包含有关我最终将获得的DIB格式的所有细节。
当我调用GetDIBits()时,为什么我没有将位图数据作为DIB获取到buff?
答案 0 :(得分:0)
我不知道你用来访问PDF文件内部结构的库,但是手头的问题会有树不同的子问题:
查找所有图片
图像可以在内容流内或附加到词典的流中发生。要查找内容流中的所有图像,您需要在Pages,XObjects或Patterns中查找所有内容流。每个都可以有一个资源 - >引用所有XObject的XObject字典(和XObject可以是图像)。
如果您避开内联图像,则可能只是扫描PDF文件,并且可以解码XObject子类型Image的每个dectionary。
解码
PDF文件中单独对象中的所有流(内容流中的内联)都是编码的,并且需要使用Decode数组进行后期处理。您需要能够执行多个过滤器才能进行解码。 Flate解码(ZLIB),JPEG和CCITT(传真G3 / G4)可能是最常用于图像的。希望您使用的PDF库知道如何解码流..
接下来是Decode数组(有点罕见),其中每个颜色分量可以从输入值缩放到输出值。这是一个线性转换。
致DIB
接下来是将解码图像转换为DIB。这意味着你需要将颜色组件转换为Windows可以“获取”的东西(例如,调色板,RGB的灰度(特殊调色板).PDF支持非常多种颜色空间并将它们转换为RGB是没有必要的。你最好希望这里需要处理的PDF只使用选择子集(如RGB和调色板)。现在可以通过创建位图头(BITMAPINFO)简单地创建DIB,填写所有数据并调用DIB创建函数CreateDIBSection和他们按照您的应用需求处理DIB。
后记
总而言之:能够处理所有PDF文件并查找所有图像是一项相当艰巨的任务,如果您控制源代码,如果是PDF并且您知道它们始终采用DeviceRGB格式且始终为JPEG等,并且从未内联到它可以做的内容流。