IIXC_Page to DIB  SOLVED

PDF-XChange Editor SDK for Developers

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Post Reply
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

IIXC_Page to DIB

Post by jeffp »

I'm using a lot of your image calls but sometimes I need to manipulate the image in other programs that use DIBs. As such, I need some code that will convert your IIXC_Page into a DIB (Device Independent Bitmap) and vice versa.

Do you have any code that would help me here.

I'm using Delphi.

Thanks.

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

Here's the sample code:

Code: Select all

//Bitmap to IIXC_Page
Bitmap bmp = (Bitmap)Bitmap.FromFile(sFileName);
uint hHB = (uint)bmp.GetHbitmap();
PDFXEdit.IIXC_Inst iInst = (PDFXEdit.IIXC_Inst)pdfCtl.Inst.GetExtension("IXC");
PDFXEdit.IIXC_Page iPage = iInst.Page_CreateFromHBITMAP(hHB, 0);
//IIXC_Page to Bitmap
Bitmap image = new Bitmap((int)(iPage.Rect.right - iPage.Rect.left), (int)(iPage.Rect.bottom - iPage.Rect.top));
Graphics g = Graphics.FromImage(image);
g.Clear(Color.White);
IntPtr hdc = g.GetHdc();
iPage.DrawToDC((uint)hdc, 0, 0, iPage.Rect.right - iPage.Rect.left, iPage.Rect.bottom - iPage.Rect.top, 0, 0);
g.ReleaseHdc(hdc);
image.Save("D:\\PageImage.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

I can already to IIXC_Page to TBitmap, but a DIB is different that a TBitmap.

For example, a DIB has a DPI but a TBitmap does not. If I go from IIXC_Page to TBitmap, I lose the IIXC_Page DPI. It doesn't carry over to the TBitmap.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

I see, well I will try to prepare you a sample with a DIB then if it's the Bitmap itself that is critical. Though you needed an overall code.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

No. The bitmap is not critical.

Here's my flow.

I will open the image with your DLL so I will get a IIXC_Page. I then have another image library that has some image manipulation calls I need, but it takes as an input a DIB. So I will need to convert the IIXC_Page to a DIB. Then once done manipulating the DIB, I will then pass the DIB back to the IIXC_Page.

So I will need

IIXC_Page to DIB

and

DIB to IIXC_Page

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

I see, then I will try to make you a sample tomorrow.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Any progress on this one?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

We do not have any time for this yet due to the 319 release. We will try to prepare a small sample in a few days.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

That's fine. Thanks for the update.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

:)
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Any more progress on this?

In looking at this further, I'll need both of the following conversions.

IIXC_Page to DIB

and

DIB to IIXC_Page

I'm receiving a DIB in memory from a scanner and I need to convert it to a IIXC_Page while preserving all the DIB info such as DPI, bits per pixel, etc.

Currently you have a IIXC_Inst.Page_CreateFromHBITMAP but this does not work with a true DIB. A DIB and HBITMAP are different animals.

Thanks again.

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

What class/structure do you use for storing DIB?

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

I'm not sure I know what you mean.

I'm programming in Delphi so anything it can handle.

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

What exactly are you getting from the scanner, or to rephrase, how do you store the information that you have got from scanner? Some class, structure etc?

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

In Delphi, the value from the scanner just comes back as a Cardinal value.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

Here's the Delphi code sample:

Code: Select all

procedure TForm1.actDrawImageExecute(Sender: TObject);
var
  bmp: TBitmap;
  ImgPage: PDFXEdit_TLB.IIXC_Page;
begin
  bmp := TBitmap.Create;
  try
    bmp.LoadFromFile('cat_banjo.bmp');
    BmpToImage(bmp, ImgPage);
  finally
    FreeAndNil(bmp);
  end;

  bmp := TBitmap.Create();
  try
    ImageToBmp(ImgPage, bmp);
    bmp.SaveToFile('test.bmp');
  finally
    FreeAndNil(bmp);
  end;
end;

procedure TForm1.ImageToBmp(const Img: PDFXEdit_TLB.IIXC_Page; var bmp: TBitmap);
var
  nWidth, nHeight: Cardinal;
Begin
  img.Get_Width(nWidth);
  img.Get_Height(nHeight);
  bmp.SetSize(nWidth, nHeight);
  img.DrawToDC(bmp.Canvas.Handle, 0, 0, nWidth, nHeight, 0, 0, 0);
End;
procedure TForm1.BmpToImage(const bmp: TBitmap; var Img: PDFXEdit_TLB.IIXC_Page);
var
  iInst: PDFXEdit_TLB.IIXC_Inst;
Begin
  Assert(bmp.HandleType = bmDIB);
  iInst := PXV_Control1.Inst.GetExtension('IXC') as PDFXEdit_TLB.IIXC_Inst;
  iInst.Page_CreateFromHBITMAP(bmp.Handle,0, Img);
End;
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

I have already been able to convert a Delphi TBitmap to IIXC_Page and vice versa.

What I'm taking about is a Windows DIB, not a TBitmap.

The conversion from a Windows DIB to a Delphi TBitmap drops some of the properties like DPI, etc. I'm looking to convert a Windows DIB directly to IIXC_Page and vice versa, thereby preserving DPI, etc.

Several of my scanner programs return a Windows DIB and that I need to load into IIXC_Page so that I can make further manipulations.

Here's a description of the DIB (as compared to other types of image formats) from the image package I use to convert DIBs currently (looking to replace it with yours). Again, a DIB will essentially be represented in Delphi with just a Cardinal, which is really just an pointer to the DIB.
Converting between DIB and other image formats
Microsoft, never content to offer one solution when it can offer two (or more), has
over the years created at least five widely-used classes of image object:
1. The Device-Independent Bitmap or DIB.
EZTwain Pro uses this format internally, representing each image as a global
handle to a block of memory containing a DIB header immediately followed by
the pixel data. DIBs can store a wide variety of image formats, and retain
resolution (DPI) information. In native Windows API programming, the DIB is the
standard general-purpose image format, although it is usually referenced using
pointers rather than a global handle.
2. The Device-Dependent Bitmap, DDB, or HBITMAP.
Often simply called a ‘bitmap’, and referenced in the Windows API by a handle
called an HBITMAP, a DDB has a device-dependent pixel format (although
actually the 1-bit format is standardized) and can only be manipulated by the
video device driver that created it. DDBs do not store resolution (DPI)
information. It is not generally meaningful to save a DDB to a file.
Today, DDBs are only useful in two contexts: They are still the easiest way to
embed fixed graphics as resources into a Windows program in C/C++. And if you
need the absolute maximum speed, they are probably the fastest way to move
pixels to and from the display.
EZTwain can convert from DDB (HBITMAP) to DIB with DIB_FromBitmap.
3. The DibSection
This is a strange hybrid object, an HBITMAP that wraps a DIB. Many languages
and imaging classes (such as GDI+, .NET Image, Delphi TBitmap) do not easily
accept DIBs but readily accept a DIBSection as an HBITMAP.
EZTwain can convert a DIB to a DibSection with DIB_ToDibSection. Use this
function when you need an HBITMAP. Note: DIB_ToDibSection frees the DIB.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

We are filling the DIBSECTION from the bitmap handle that you pass to the Page_CreateFromHBITMAP method. We are using the DPI information and some other important stuff required for our inner format. Some of the information, that is not crucial is omitted and will not be stored.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Ok. But my issue still remains.

I receive a Windows DIB (described in my last post) in the form of a Cardinal value or pointer from the scanner program.

I now need to convert that into a IIXC_Page

So the functions I'm after would look like this

function DIBToIXCPage(HDib: Cardinal): IIXC_Page;

function IXCPageToDIB(APage: IIXC_Page): Cardinal;

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

Use this method to convert the DIB handle to the HBITMAP:

Code: Select all

HBITMAP DIB_ToDibSection(HANDLE hdib)
Then pass the HBITMAP to the Page_CreateFromHBITMAP method in our SDK.
If the DIB_ToDibSection method will neglect the DPI then you can use the DIB_XResolution / DIB_YResolution methods to save the DPI and then set the IIXC_Page's DPI manually:

Code: Select all

iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_XDPI, xDpi);
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_YDPI, yDpi);
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Where are you getting the DIB_ToDibSection and DIB_XResolution calls?

I have them in the EZTWAIN library that I use, but I'm trying to replace that library. Are you referring to EZTWAIN or are these calls available in a general Windows library?

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Well you haven't provided us enough information so we started searching, as soon as we got the EZTWAIN keyword. This gave us a little explanation of what exactly were you doing. Now, if you can give us a piece of code that you were using with EZTWAIN to convert from the Cardinal values to DIB then we can proceed further.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

All the DIB_ calls in EZTWAIN are inside a compiled DLL so I don't think that's going to help.

All I'm asking here is that it appears that the DIB in the context of EZTWAIN is some generally accepted Windows format. I'm just asking if you are familiar with this format and if so can you write a conversion to and from your IIXC_Page interface without calling into the DIB_ calls in EZTWAIN.

I can continue to include the EZTWAIN dll in my distrib files so I can make this conversion with their calls, but I'd prefer not to.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Can you give us a code snippet that will show:
1) How are you getting the data from scanner.
2) How are you giving this data to EZTWAIN?

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Ok. This is from your old Scan DLL. The image is passed in the pData item in the GetData call below. I then change it to

HDib := Cardinal(pData);

and then work with HDib in the rest of my code. I'd like to convert this HDIB into a IIXC_Page object and vice versa.

Code: Select all


procedure GetData(userData: LongWord; pData: pointer; DataSize: LongWord); stdcall;
begin
  if (userData <> 0 ) and Assigned(TTrackerScanLib(userData)) then
  begin
    TTrackerScanLib(userData).DoOnGetData(pData, DataSize);
  end;
end;

procedure TTrackerScanLib.DoOnGetData(pData: pointer; DataSize: LongWord);
var
  HDib: Cardinal;
begin
  //pData seems to be freed by Tracker
  FIsProcessing := Assigned(pData) and (DataSize > 0);
  if FIsProcessing and Assigned(FOnGetHDib) then
  begin
    HDib := Cardinal(pData);
    //GlobalLock(HDib);
    FOnGetHDib(HDib); //DO NOT FREE HDIB inside Event or Tracker will Freeze
    //GlobalUnlock(HDib);
    //Don't Free this one. Tracker seems to do this.
  end;
end;

function TTrackerScanLib.CreateTwainObject: Boolean;
var
  UnlockKey, DevKey: string;
  hr: HRESULT;
begin
  Result := False;
  if Assigned(FTwain) then
  begin
    Result := True;
    exit;
  end;

  FTwain := SXC_CreateTwainObject(FRegKey, FDevCode);
  if not Assigned(FTwain) then
  begin
    FErrorStr := 'Could not create Twain Object';
    exit;
  end;

  hr := SXC_InitTwain(FTwain);
  if not IsError(hr) then
  begin
    SXC_SetProc(FTwain, GetData, Integer(Self));
    Result := True;
  end;
end;

Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

Now, finally everything is clear. I'm giving you a code pieces from our project:

Code: Select all

HRESULT hRes = DS_OK;
BITMAPINFOHEADER* lpBMHeader = reinterpret_cast<BITMAPINFOHEADER*>(const_cast<BYTE*>(pData));

DWORD			PalSize = 0;
IXC_MemoryType	type = MemoryType_1bpp;
DWORD			colors_count = 0;
RGBQUAD*		pPalette = NULL;
int				offset = 0;
const BYTE*		pDataForCodec = NULL;

switch (lpBMHeader->biBitCount)
{
case 1:
{
	colors_count = PalSize = 2;
	type = MemoryType_1bpp;
}
break;
case 4:
{
	if (lpBMHeader->biClrUsed != 0)
		colors_count = PalSize = lpBMHeader->biClrUsed;
	else
		colors_count = PalSize = 16;

	if (lpBMHeader->biCompression == BI_RLE4)
		type = MemoryType_4RLE;
	else
		type = MemoryType_4bpp;
}
break;
case 8:
{
	if (lpBMHeader->biClrUsed != 0)
		colors_count = PalSize = lpBMHeader->biClrUsed;
	else
		colors_count = PalSize = 256;

	if (lpBMHeader->biCompression == BI_RLE8)
		type = MemoryType_8RLE;
	else
		type = MemoryType_8bpp;
}
break;
case 16:
case 24:
case 32:
{
	if (lpBMHeader->biCompression == BI_BITFIELDS)
	{
		PalSize = 3;
	}
	else
	{
		if (lpBMHeader->biClrUsed)
			PalSize = lpBMHeader->biClrUsed;
	}

	switch (lpBMHeader->biBitCount)
	{
	case 16:
		type = MemoryType_16bpp;
		break;
	case 24:
		type = MemoryType_24bpp;
		break;
	case 32:
		type = MemoryType_32bpp;
		break;
	default:
		hRes = PXV_ERR_INTERNAL;
	}
}
break;
default:
	hRes = PXV_ERR_INVALID_ARG;
}

PalSize *= sizeof(RGBQUAD);
if (colors_count != 0)
	pPalette = (RGBQUAD*)(pData + sizeof(BITMAPINFOHEADER));

pDataForCodec = pData + sizeof(BITMAPINFOHEADER) + PalSize;

offset = (((lpBMHeader->biBitCount * lpBMHeader->biWidth) + 31) / 32) * 4;

if (lpBMHeader->biHeight < 0 && lpBMHeader->biCompression != BI_RLE8 && lpBMHeader->biCompression != BI_RLE4)
{
	pDataForCodec += (-lpBMHeader->biHeight - 1) * offset;
	offset = -offset;
}

DWORD Height = (DWORD)(lpBMHeader->biHeight > 0 ? lpBMHeader->biHeight : -(lpBMHeader->biHeight));

IIXC_Page* pPage = nullptr;
ixcInst.Page_CreateFromMemory(lpBMHeader->biWidth, Height, type, colors_count, pPalette, pDataForCodec, offset, dwDataSize - (sizeof(BITMAPINFOHEADER) + PalSize), 0, &pPage);

if ((lpBMHeader->biXPelsPerMeter != 0) && (lpBMHeader->biYPelsPerMeter != 0))
{
	UINT xDPI = MulDiv(lpBMHeader->biXPelsPerMeter, 254, 10000);
	UINT yDPI = MulDiv(lpBMHeader->biYPelsPerMeter, 254, 10000);

	HRESULT hDPI = pPage->put_FmtInt(FP_ID_XDPI, xDPI);
	hDPI = pPage->put_FmtInt(FP_ID_YDPI, yDPI);
}
hRes = pPage->put_FmtInt(FP_ID_ITYPE, ImageFormat_Auto);
hRes = pPage->put_FmtInt(FP_ID_FORMAT, FMT_PNG_ID);


Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

One follow up for now.

How do you set the value of

dwDataSize

which is one of the values you use in Page_CreateFromMemory

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

That one you should get from the Callback with the pData.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

That was just one example I sent. Most just give me the HDib and that's all.

For example, in the EZTWAIN library there is a call

HDib := DIB_LoadPage(AFile, 0);

Which just returns a HDIB that I want to be able to convert to IIXC_Page as well.

Is there a way to compute the DataSize of the HDib from just the HDib itself to use in Page_CreateFromMemory?

--Jeff
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Ok. I figured out how to calculate the right DataSize from the HDib info.

So here is my code in Delphi produced by translating your sample.

However, it doesn't quite work. I'm getting good results with BW 200dpi, but when I go to Color or 300 DPI, the image comes out stretched and funning. Any thoughts on the code below?

I start with an HDib which is really just your Integer(pData)

--Jeff

Code: Select all


function DibToPage(HDib: Cardinal): IIXC_Page;
var
  pData: Pointer;
  pHeader: PBITMAPINFOHEADER;
  PalSize, Height, Width, DataSize: LongWord;
  MemType: IXC_MemoryType;
  NumColors: Integer;
  pPalette: PLongWord;
  Offset, xDPI, yDPI: Integer;
  pDataForCodex: PByte;
begin
  Result := nil;
  PalSize := 0;
  MemType := MemoryType_1bpp;
  NumColors := 0;
  pPalette := nil;
  Offset := 0;
  pDataForCodex := nil;

  GlobalLock(HDib);
  try
    pData := Pointer(HDib);
    pHeader := PBITMAPINFOHEADER(pData);

    case pHeader.biBitCount of
      1:
      begin
        NumColors := 2;
        PalSize := 2;
        MemType := MemoryType_1bpp;
      end;
      4:
      begin
        if (pHeader.biClrUsed <> 0) then
        begin
          NumColors := pHeader.biClrUsed;
          PalSize := pHeader.biClrUsed;
        end else
        begin
          NumColors := 16;
          PalSize := 16;
        end;
        if (pHeader.biCompression = BI_RLE4) then MemType := MemoryType_4RLE else MemType := MemoryType_4bpp;
      end;
      8:
      begin
        if (pHeader.biClrUsed <> 0) then
        begin
          NumColors := pHeader.biClrUsed;
          PalSize := pHeader.biClrUsed;
        end else
        begin
          NumColors := 256;
          PalSize := 256;
        end;
        if (pHeader.biCompression = BI_RLE8) then MemType := MemoryType_8RLE else MemType := MemoryType_8bpp;
      end;
      16, 24, 32:
      begin
        if (pHeader.biCompression = BI_BITFIELDS) then
        begin
          PalSize := 3;
        end else
        begin
          if (pHeader.biClrUsed <> 0) then PalSize := pHeader.biClrUsed;
        end;

        case pHeader.biBitCount of
          16: MemType := MemoryType_16bpp;
          24: MemType := MemoryType_24bpp;
          32: MemType := MemoryType_32bpp;
        end;
      end;
    end;

    PalSize := PalSize * SizeOf(RGBQUAD);
    if (NumColors <> 0) then pPalette := PLongWord(Integer(pData) + SizeOf(BITMAPINFOHEADER));

    pDataForCodex := PByte(Integer(pData) + SizeOf(BITMAPINFOHEADER) + PalSize);
    Offset := Floor((((pHeader.biBitCount * pHeader.biWidth) + 31) / 32) * 4);

    if (pHeader.biHeight < 0) and (pHeader.biCompression <> BI_RLE8) and (pHeader.biCompression <> BI_RLE4) then
    begin
      pDataForCodex := pDataForCodex + (-pHeader.biHeight - 1) * Offset;
      Offset := -Offset;
    end;

    Width := pHeader.biWidth;
    Height := Abs(pHeader.biHeight);
    DataSize := pHeader.biSizeImage + SizeOf(BITMAPINFOHEADER) + PalSize;

  
    INST_IXC.Page_CreateFromMemory(Width, Height, MemType, NumColors, pPalette^, pDataForCodex^, Offset, DataSize - (SizeOf(BITMAPINFOHEADER) + PalSize), 0, Result);
  

    if Assigned(Result) and (pHeader.biXPelsPerMeter <> 0) and (pHeader.biYPelsPerMeter <> 0) then
    begin
      xDPI := MulDiv(pHeader.biXPelsPerMeter, 254, 10000);
      yDPI := MulDiv(pHeader.biYPelsPerMeter, 254, 10000);

      Result.Set_FmtInt(FP_ID_XDPI, xDPI);
      Result.Set_FmtInt(FP_ID_YDPI, yDPI);
    end;
  finally
    GlobalUnlock(HDib);
  end;
end;
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,
That was just one example I sent. Most just give me the HDib and that's all.
You mean that you are using some other sources along with our scanner?
The SXC_SetProc method has the callback with these values:

Code: Select all

(DWORD_PTR pUserData, const BYTE* pData, DWORD dwDataSize)
As for your code - we will check it out and look for potential problems.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

Hello Jeff,

We found a bug in your translation from the C++ code. You have not calculated the offset correctly - here's the correct code:

Code: Select all

Offset := Floor(((pHeader.biBitCount * pHeader.biWidth) + 31) / 32) * 4;
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB  SOLVED

Post by jeffp »

Yes! That was it. It now seems to work in all cases.

Thanks so much for your help on this one. You guys are awesome.

I'm posting my final Delphi code below for anyone else needing this.

Thanks again.

Code: Select all


function DibToIXCPage(HDib: Cardinal): IIXC_Page;
var
  pData: Pointer;
  pHeader: PBITMAPINFOHEADER;
  PalSize, Height, Width, DataSize: LongWord;
  MemType: IXC_MemoryType;
  NumColors: Integer;
  pPalette: PLongWord;
  Offset, xDPI, yDPI: Integer;
  pDataForCodex: PByte;
begin
  Result := nil;
  PalSize := 0;
  MemType := MemoryType_1bpp;
  NumColors := 0;
  pPalette := nil;
  Offset := 0;
  pDataForCodex := nil;

  GlobalLock(HDib);
  try
    pData := Pointer(HDib);
    pHeader := PBITMAPINFOHEADER(pData);

    case pHeader.biBitCount of
      1:
      begin
        NumColors := 2;
        PalSize := 2;
        MemType := MemoryType_1bpp;
      end;
      4:
      begin
        if (pHeader.biClrUsed <> 0) then
        begin
          NumColors := pHeader.biClrUsed;
          PalSize := pHeader.biClrUsed;
        end else
        begin
          NumColors := 16;
          PalSize := 16;
        end;
        if (pHeader.biCompression = BI_RLE4) then MemType := MemoryType_4RLE else MemType := MemoryType_4bpp;
      end;
      8:
      begin
        if (pHeader.biClrUsed <> 0) then
        begin
          NumColors := pHeader.biClrUsed;
          PalSize := pHeader.biClrUsed;
        end else
        begin
          NumColors := 256;
          PalSize := 256;
        end;
        if (pHeader.biCompression = BI_RLE8) then MemType := MemoryType_8RLE else MemType := MemoryType_8bpp;
      end;
      16, 24, 32:
      begin
        if (pHeader.biCompression = BI_BITFIELDS) then
        begin
          PalSize := 3;
        end else
        begin
          if (pHeader.biClrUsed <> 0) then PalSize := pHeader.biClrUsed;
        end;

        case pHeader.biBitCount of
          16: MemType := MemoryType_16bpp;
          24: MemType := MemoryType_24bpp;
          32: MemType := MemoryType_32bpp;
        end;
      end;
    end;

    PalSize := PalSize * SizeOf(RGBQUAD);
    if (NumColors <> 0) then pPalette := PLongWord(Integer(pData) + SizeOf(BITMAPINFOHEADER));

    pDataForCodex := PByte(Integer(pData) + SizeOf(BITMAPINFOHEADER) + PalSize);
    Offset := Floor(((pHeader.biBitCount * pHeader.biWidth) + 31) / 32) * 4;

    if (pHeader.biHeight < 0) and (pHeader.biCompression <> BI_RLE8) and (pHeader.biCompression <> BI_RLE4) then
    begin
      pDataForCodex := pDataForCodex + (-pHeader.biHeight - 1) * Offset;
      Offset := -Offset;
    end;

    Width := pHeader.biWidth;
    Height := Abs(pHeader.biHeight);
    DataSize := pHeader.biSizeImage;

    INST_IXC.Page_CreateFromMemory(Width, Height, MemType, NumColors, pPalette^, pDataForCodex^, Offset, DataSize, 0, Result);

    if Assigned(Result) and (pHeader.biXPelsPerMeter <> 0) and (pHeader.biYPelsPerMeter <> 0) then
    begin
      xDPI := MulDiv(pHeader.biXPelsPerMeter, 254, 10000);
      yDPI := MulDiv(pHeader.biYPelsPerMeter, 254, 10000);

      Result.Set_FmtInt(FP_ID_XDPI, xDPI);
      Result.Set_FmtInt(FP_ID_YDPI, yDPI);
    end;
  finally
    GlobalUnlock(HDib);
  end;
end;

Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

:)
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

Would you happen to have a code sample to do the reverse

function IXCPageDib(APage: IIXC_Page): Cardinal;
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IIXC_Page to DIB

Post by Sasha - Tracker Dev Team »

And why would you need that?
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: IIXC_Page to DIB

Post by jeffp »

To round out my library :-)

But not a high priority at this point though.

I'll check back on this one when/if it becomes necessary.

Thanks again for the DibToIXCPage. That one was critical.

--Jeff
User avatar
Tracker Supp-Stefan
Site Admin
Posts: 17910
Joined: Mon Jan 12, 2009 8:07 am
Location: London
Contact:

Re: IIXC_Page to DIB

Post by Tracker Supp-Stefan »

Hi Jeff,

Thanks for the update!
Do let us know if this becomes necessary.

Regards,
Stefan
Post Reply