Welcome Guest! To enable all features, please Login or Register.

Notification

Icon
Error

Options
View
Last Go to last post Unread Go to first unread post
#1 Posted : Friday, October 15, 2010 7:10:46 AM(UTC)
datafunc

Groups: Registered
Posts: 3


I am using the LeadTools version 14.5 with pdf support. The code I am about to display works but the conversion of each pdf page seems slower than it should. I thought I could remedy it by passing the FILEINFO struct to the L_LoadBitmap function but when I do that it doesn't seem to be using the correct information. Can anyone shed some light on this situation? I need to know why when I pass my fileInfo var into the L_LoadBitmap it doesn't work even if I modify the fileInfos page # each time I change the loadfileoptions page #.

Also, I would like to store the bitmap into memory for use with multi-threading to convert large pdf files multiple pages at a time. Would this be thread safe if I called L_LoadBitmapMemory with a different page each time?

    unsigned WINAPI ConvertMultiImgToSingleImg(LPVOID param)
    {
        MultiToSingleThreadData * tInfo = (MultiToSingleThreadData *) param;

        BITMAPHANDLE    bmapHandle;
        LOADFILEOPTION    loadFileOptions;
        FILEINFO        fileInfo;

        ZeroMemory(&loadFileOptions, sizeof(LOADFILEOPTION));
        ZeroMemory(&bmapHandle, sizeof(BITMAPHANDLE));
        ZeroMemory(&fileInfo, sizeof(FILEINFO));

        UINT    error = 0;
        if(!Path::IsPathValid(tInfo->outputFilename))
            error = IMG_CONV_ERROUTFNAME;
        if(!Path::IsPathValid(tInfo->inputFilename))
            error = IMG_CONV_ERRINFNAME;
        else if(L_FileInfo(tInfo->inputFilename, &fileInfo, sizeof(FILEINFO), FILEINFO_TOTALPAGES, NULL) != SUCCESS)
            error = IMG_CONV_FAILED;
        else
        {
            tInfo->pageTotal = fileInfo.TotalPages;
            tInfo->pageCurrent = 1;
        }
        if(tInfo->eventTotalPage != NULL)
            SetEvent(tInfo->eventTotalPage);
        if(error != 0)
        {
            _endthreadex(error);
            return 0;
        }

        if(fileInfo.Format == FILE_RAS_PDF)
        {
            FILEPDFOPTIONS    pdfOptions;

            ZeroMemory(&pdfOptions, sizeof(FILEPDFOPTIONS));

            if(L_GetPDFOptions(&pdfOptions, sizeof(FILEPDFOPTIONS)) != SUCCESS)
            {
                _endthreadex(IMG_CONV_FAILED);
                return 0;
            }

            pdfOptions.nXResolution = 300;
            pdfOptions.nYResolution = 300;
            if(L_SetPDFOptions(&pdfOptions) != SUCCESS)
            {
                _endthreadex(IMG_CONV_FAILED);
                return 0;
            }
        }
        if(L_GetDefaultLoadFileOption(&loadFileOptions, sizeof(LOADFILEOPTION)) != SUCCESS)
        {
            _endthreadex(IMG_CONV_FAILED);
            return 0;
        }

        stdstring fileNoExt, filePath;
        try
        {
            fileNoExt = Path::GetFilenameNoExt(tInfo->outputFilename);
            filePath = Path::GetPathNoFilename(tInfo->outputFilename);

            tInfo->pagesConverted = 0;
            for(int i = 1; i <= fileInfo.TotalPages; i++)
            {
                if(tInfo->stopConversion)
                {
                    _endthreadex(IMG_CONV_STOPPED);
                    return 0;
                }

                ZeroMemory(tInfo->currentOutputFile, sizeof(tInfo->currentOutputFile));
                _stprintf_s(tInfo->currentOutputFile, sizeof(tInfo->currentOutputFile), _T("%s.%.3d"), Path::Combine(filePath.c_str(), fileNoExt.c_str()).c_str(), i);

                loadFileOptions.PageNumber = i;
                tInfo->pageCurrent = i;
                if(L_LoadBitmap(tInfo->inputFilename, &bmapHandle, sizeof(BITMAPHANDLE), 0, ORDER_RGB, &loadFileOptions, NULL) != SUCCESS)
                    continue;
                if(L_SaveBitmap(tInfo->currentOutputFile, &bmapHandle, tInfo->outputFileType, 0, NULL, NULL) != SUCCESS)
                {
                    L_FreeBitmap(&bmapHandle);
                    continue;
                }
                tInfo->pagesConverted++;
                L_FreeBitmap(&bmapHandle);
            }
        }
        catch(dferror &e)
        {
        }

        _endthreadex(0);

        return 0;
    }
 

Try the latest version of LEADTOOLS for free for 60 days by downloading the evaluation: https://www.leadtools.com/downloads

Wanna join the discussion? Login to your LEADTOOLS Support accountor Register a new forum account.

#2 Posted : Sunday, October 17, 2010 5:02:00 AM(UTC)

Basel  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Loading PDF in v14.5 cannot be done in multiple threads. Other parts of the toolkit support multithreading, but not PDF loading.

If you use our toolkit to load PDF in a single-threaded program and you face problems with page numbers, please create a small sample project (not your full application) and put it in a ZIP or RAR file and send it to me. You can post it here or send it to support@leadtools.com and mention this forum post.

 
#3 Posted : Wednesday, November 3, 2010 8:36:36 AM(UTC)
datafunc

Groups: Registered
Posts: 3


I apologize for the lapse in time from my previous post. We had some more pertinent issues come up that required my attention. Anyhow, I threw together a quick test program and realized what my initial problem was. I just changed where I called the L_FileInfo() from and I was able to pass it in the function because I suppose it picked up the changes to the PDFOptions. The only issue remaining now is that I thought by passing that FILEINFO struct to the L_LoadBitmap function it would dramatically increase the speed in which it did the conversions but if there was a performance increase it was negligible. The conversion rate from my calculations is approximately 1 second per page of the pdf file to convert to tif. About half a second for loading each bitmap and saving each bitmap. I noticed with lower Resolution settings this length of time it took to do each conversion was considerably lower. I suppose my only remaining question now is, could I optimize my program to do it any faster, or is this the expected time it takes? I am unfamiliar with the algorithms for manipulating image files so I just wanted to make sure this was an appropriate speed. The issue has come about because some of our customers are looking to convert 3-400 page PDF's and at about a second a piece we're looking around 5 to 6 minutes. Here is the code attached in the zip.

#include "windows.h"
#include "l_bitmap.h"
#include <string>
#include <sstream>
#include <iostream>

typedef std::string stdstr;
typedef std::stringstream sstream;

int main()
{
    BITMAPHANDLE    bmapHandle;
    LOADFILEOPTION    loadFileOptions;
    FILEPDFOPTIONS    filePdfOptions;
    FILEINFO        fileInfo;

    memset(&bmapHandle, 0, sizeof(bmapHandle));
    memset(&loadFileOptions, 0, sizeof(loadFileOptions));
    memset(&fileInfo, 0, sizeof(fileInfo));
    memset(&filePdfOptions, 0, sizeof(filePdfOptions));

    char    inputFile[260] = "test.pdf";

    // Start Image Manip Code

    L_UnlockSupport(L_SUPPORT_PDF, L_KEY_PDF);
    L_UnlockSupport(L_SUPPORT_LTPRO, L_KEY_LTPRO);
    // This is where I am a little confused, and maybe I didn't read the documentation well enough.
    // Could I bypass the calls to L_GetPDFOptions and L_SetPDFOptions and just use the
    // LOADFILEOPTION.XResolution and .YResolution members to modify the way the PDF file is loaded?
    // I do nothing with the FILEPDFOPTIONS var after this point.
    if(!L_GetPDFOptions(&filePdfOptions, sizeof(filePdfOptions)))
        std::cout<< "Loading pdfOptions failed";
    filePdfOptions.nXResolution = 300;
    filePdfOptions.nYResolution = 300;
    if(!L_SetPDFOptions(&filePdfOptions))
        std::cout<< "Setting pdfOptions failed";
    if(!L_FileInfo(inputFile, &fileInfo, sizeof(fileInfo), FILEINFO_TOTALPAGES, NULL))
        std::cout<< "Loading fileInfo failed";
    if(!L_GetDefaultLoadFileOption(&loadFileOptions, sizeof(loadFileOptions)))
        std::cout<< "Loading fileOptions failed";

    for(int i = 1; i <= fileInfo.TotalPages; i++)
    {
        loadFileOptions.PageNumber = i;

        std::cout<< "Loading pdf file page " << i << std::endl;
        fileInfo.PageNumber = i;
        if(!L_LoadBitmap(inputFile, &bmapHandle, sizeof(bmapHandle), 0, ORDER_RGB, &loadFileOptions, &fileInfo))
        {
            std::cout<< "Could not load file " << inputFile << " ." << std::endl;
            continue;
        }
        sstream outFile;
        outFile<< "test" << i << ".tif";
       
        char annoyingVar[260];
        strcpy_s(annoyingVar, sizeof(annoyingVar), outFile.str().c_str());
        std::cout<< "Writing tif file " << outFile.str() << std::endl;
        // Why does this function not take a const L_TCHAR * as it's first parameter? Does it do some string manipulation?
        if(!L_SaveBitmap(annoyingVar, &bmapHandle, FILE_CCITT_GROUP4, 0, NULL, NULL))
            std::cout<< "File " << outFile.str() << " could not be saved." << std::endl;
        L_FreeBitmap(&bmapHandle);
    }

    char exitChar;

    std::cin>> exitChar;

    return 0;
}
 
#4 Posted : Thursday, November 4, 2010 6:57:10 AM(UTC)

Basel  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

The main factor that causes loading PDF at a higher resolution to be slower is the process of rasterizing.
In LEADTOOLS, the contents of each PDF page (text, graphics, images, etc.) are converted to one raster (bitmap) image during loading. Increasing the loading resolution leads to more processing and memory requirements, but produces a higher quality image. There's nothing much you can do about this except decide on the best compromise between speed and quality for your application.

The only factors that affects PDF loading resolution (DPI) are the LOADFILEOPTION.XResolution and .YResolution structure members, which must be used through the L_SetPDFOptions function.

Note:
You don't need the annoyingVar. You should be able to pass any valid char pointer, but depending on its type, you might have to cast it.
 
#5 Posted : Thursday, November 4, 2010 7:37:01 AM(UTC)
datafunc

Groups: Registered
Posts: 3


Thanks for the help. I appreciate all the input.

I guess what I was getting at with the annoyingVar thing was I wasn't sure if you did some internal manipulation that required a mutable char * so I just always opted to pass it one.
 
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF.NET | YAF.NET © 2003-2024, Yet Another Forum.NET
This page was generated in 0.177 seconds.