Solved

biWidth wrong in tagBITMAPINFOHEADER when using twain

Posted on 2008-06-18
6
526 Views
Last Modified: 2013-11-20
I use the twain driver to scan an image. Then I read the raw image data i get a wrong width for the following dpi-resolutions:
96 dpi -> the width is to low by 3
100 dpi -> the width is to low by 2

I have attached an image to show this.

On higher Resolutions (150, 300, 360dpi) it always works.

What did I wrong? Is there a differnet way to get the hight and width of an hDIB?

The strange thing is it that these resolutions work perfect in other programms (e.g. IrfanView)

Please Help

Greedings Sonja
bool CScanDialog::PDFAddPicturePage(HDIB hDIB)

{

  HPDF_Page  page;

  HPDF_Image image;
 

  BYTE * BGRimage;

  BGRimage = (BYTE *) GlobalLock(hDIB);
 

  /*

    typedef struct tagBITMAPINFOHEADER{

      DWORD  biSize; 

      LONG   biWidth; 

      LONG   biHeight; 

      WORD   biPlanes; 

      WORD   biBitCount; 

      DWORD  biCompression; 

      DWORD  biSizeImage; 

      LONG   biXPelsPerMeter; 

      LONG   biYPelsPerMeter; 

      DWORD  biClrUsed; 

      DWORD  biClrImportant; 

    } BITMAPINFOHEADER, *PBITMAPINFOHEADER; 

  */
 

  long img_width    = * (BGRimage + 1 * sizeof(DWORD) + 3); img_width *= 0x100;

       img_width   += * (BGRimage + 1 * sizeof(DWORD) + 2); img_width *= 0x100;

       img_width   += * (BGRimage + 1 * sizeof(DWORD) + 1); img_width *= 0x100;

       img_width   += * (BGRimage + 1 * sizeof(DWORD)    );

  long img_height   = * (BGRimage + 1 * sizeof(DWORD) + 1 * sizeof(long) +3);img_height *= 0x100;

       img_height  += * (BGRimage + 1 * sizeof(DWORD) + 1 * sizeof(long) +2);img_height *= 0x100;

       img_height  += * (BGRimage + 1 * sizeof(DWORD) + 1 * sizeof(long) +1);img_height *= 0x100;

       img_height  += * (BGRimage + 1 * sizeof(DWORD) + 1 * sizeof(long) +0);

  DWORD img_header_length  = * (BGRimage +1); img_header_length *= 0x100;

        img_header_length += * (BGRimage);
 

  BGRimage += img_header_length; // Offset of the header

  BGRimage += (0xFF * 4);        // Offset of the color table

  /*Here some  code that writes the image to a pdf file*/

}

Open in new window

Scan.JPG
0
Comment
Question by:Sonja_M
  • 2
  • 2
  • 2
6 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 21814498
In the above code, there's no reference to any DPI values nor are you setting 'biWidth'. Could you show the complete code and explain the calculations in the above snippet?
0
 

Author Comment

by:Sonja_M
ID: 21814894
Hi jkr!

To do a scan you simply have to set some parameters for the scanner and then start the scan. The DPI-Value is stored in

#define SCANNER_DPI 96

The code above is run after the scan. I get a handle to a hDIB-Image and try to use this data. The follwing is not possible, because the compile can not convert void to tagBITMAPINFOHEADER:

tagBITMAPINFOHEADER * MyDibHead = BGRimage;

So what I did is to read the raw data in line 25-28 from biWidth. Later on I do not need the dpi anymore. I just need the pixels, but I only ant to use around 100dpi then scanning.

I hope that got clearer.

Greedings

Sonja
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 199 total points
ID: 21815491
This is well possible, just use a cast, i.e.
// cast 1

BITMAPINFOHEADER * MyDibHead = (BITMAPINFOHEADER *) BGRimage;
 

// cast 2

BITMAPINFOHEADER * MyDibHead = static_cast<BITMAPINFOHEADER *>(BGRimage);

Open in new window

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 19

Accepted Solution

by:
alb66 earned 300 total points
ID: 21819747
Hi Sonja,
rimember that a line of a bitmap is always paddeed  to a DWORD boundary.

Example:
If MyDibHead.biWidth == 22 the line lenght is 24
0
 

Author Closing Comment

by:Sonja_M
ID: 31470175
Thank you very much, you both helped me a lot.

@jkr: First I tryed to cast the header - but i alway got a "can not cast"-error. Solution 1 worked (i thought I tryed this already).

@alb66: Where did you got this from? It was the solution - of course - now it works perfect. I have a white extra line now sometimes but that does not bother me. I was more afraid that a differend scanner sends me the picture with one pixel more.

Here is my final code (got much shorter):


bool CScanDialog::PDFAddPicturePage(HDIB hDIB)
{
    BYTE * BGRimage;
    BGRimage = (BYTE *) GlobalLock(hDIB);

    BITMAPINFOHEADER * MyDibHead = (BITMAPINFOHEADER *) BGRimage;
 
    long img_height = MyDibHead->biHeight;
    long img_width  = (((MyDibHead->biWidth + 3) / 4) * 4);

    BGRimage += MyDibHead->biSize;
    /*Here some  code that writes the image to a pdf file*/
}
0
 
LVL 19

Expert Comment

by:alb66
ID: 21863479
For example, you can find that information in the BITMAPINFO documentation:
http://msdn.microsoft.com/en-us/library/ms532284(VS.85).aspx

<<<<< A DIB consists of two distinct parts: a BITMAPINFO structure describing the dimensions and colors of the bitmap, and an array of bytes defining the pixels of the bitmap. The bits in the array are packed together, but each scan line must be padded with zeroes to end on a LONG data-type boundary. >>>>>
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Unable to start eclipse ? 17 133
How to open a zip file 4 62
VS2015 Redefinition errors 4 29
Bartender label printing - switch on and off graphics 3 14
The standard (non-Professional) edition of PaperPort (http://www.nuance.com/for-individuals/by-product/paperport/index.htm) from Nuance Communications (http://www.nuance.com/) (previously known as ScanSoft) is limited to five Scanning Profiles, but …
This article was inspired by a question here at Experts Exchange (http://www.experts-exchange.com/Software/Photos_Graphics/Images_and_Photos/Q_28629170.html). The requirements stated in that question are (1) reduce the file size of a large number of…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

896 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now