TWAIN Working Group

Newsletter Signup
Donate
Help keep TWAIN free
  • About TWAIN
    • What’s New?
    • News
    • Events
    • Membership
    • Consider a Donation
    • Contact Us
  • Why TWAIN?
  • Developers
    • Driver Developer
    • Application Developer
    • TWAIN Features
    • Specification & Tools
    • Self Certification Process
  • Support Forums
  • Scanner End-User
  • Find Certified Drivers
    • Facebook
    • LinkedIn
    • Vimeo

Memory transfer mode: desuming the header

Forums › TWAIN Classic › Memory transfer mode: desuming the header

  • This topic has 10 replies, 2 voices, and was last updated 11 years, 5 months ago by sdavi.
Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • August 9, 2009 at 6:42 pm #22520 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Hi all, i’m working on buffered memory transfer mode.
    I’m able to save on filesystem image data but i dont save into file
    header info of the image (the buffered memory transfer mode dont carry out with header information).
    So i’ve a question: how can i deducing the header of image? it must be a BITMAPFILEHEADER + BITMAINFOHEADER/BITMAPCOREHEADER? (this implies that i get always a bitmap?)
    How can i make the header?
    Best regards

    August 10, 2009 at 1:40 pm #24990 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Another question: when i use native mode, the scanner return me a dib handle, so i can desume BITMAPINFOHEADER and BITMAPFILEHEADER structs, save it and then the bitmap bits. it works.
    if in my app i want give to end user the choice to save image in another format, i can use any image processing library (imagemagick, freeimage etc.) but only if i save the returned image in bmp format.
    So my question: both in memory and native mode (i know that in file mode it is possible), is there any chance to give in other format (jpeg, png, tiff and so on) directly by the device???
    In twain spec. is written that in memory mode the device return the image data without header, so the programmer must deduce the headers.
    In memory mode, the returned data are always of a bitmap?

    August 12, 2009 at 2:41 pm #24991 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Now, i can get the image data by a memory transfer, desume the hneeded headers (BITMAPFLILEHEADER and BITMAPINFOHEADER),
    and i can save it into the filesystem, but when i open the image with a program (gimp for example) i note that the image is flipped vertically.
    Why???
    Anyone can say me why the source transfer image data in that way?

    Post my code in relevants parts:


    void doBufferedMemoryTransfer()
    {
    /*commented code, only explained for semplicity*/
    //call DG_CONTROL,DAT_SETUPMEMXFER,MSG_GET so i can setup twMemXFer that is of TW_SETUPMEMXFER type
    // call getImageInfo(); and getImageLayout(); that wraps DG_IMAGE,DAT_IMAGEINFO,MSG_GET and DG_IMAGE,DAT_IMAGELAYOUT,MSG_GET respectively
    // in a loop i call DG_IMAGE,DAT_IMAGEMEMXFER,MSG_GET until TWRC_XFERDONE is fired by last call to DG_IMAGE,DAT_IMAGEMEMXFER,MSG_GET
    /*end commented code*/
    ...
    case TWRC_SUCCESS:
    fwrite((void*)buf,1,(UINT)twImageMemXFer.BytesWritten,pFile);
    break;
    case TWRC_XFERDONE:
    //write last buffer into the file
    fwrite((void*)buf,1,(UINT)twImageMemXFer.BytesWritten,pFile);
    //call fseek to move the file pointer to begin of file in order to write
    //image headers that needs to be placed in
    fseek ( pFile , 0 , SEEK_SET );
    bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER) ;
    bitmapFileHeader.bfType = 0x4D42;//BM
    bitmapFileHeader.bfReserved1 = 0;
    bitmapFileHeader.bfReserved2 = 0;
    bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) ;

    bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER) ;
    bitmapInfoHeader.biPlanes = 1;
    bitmapInfoHeader.biBitCount = imageInfo->getBitsPerPixel();
    bitmapInfoHeader.biCompression = BI_RGB;//imageInfo->getCompression();
    bitmapInfoHeader.biSizeImage = ((((imageInfo->getImageWidth() * imageInfo->getBitsPerPixel() + 31) / 32)*4) * abs(imageInfo->getImageLength()));

    bitmapInfoHeader.biXPelsPerMeter = 0;
    bitmapInfoHeader.biYPelsPerMeter = 0;
    bitmapInfoHeader.biClrUsed = 0;
    bitmapInfoHeader.biClrImportant = 0;
    bitmapInfoHeader.biWidth = imageInfo->getImageWidth();
    bitmapInfoHeader.biHeight = imageInfo->getImageLength();

    fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), pFile);
    fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), pFile);
    //other calls to free memory, close file handle and exit from the loop omitted.
    break;



    }

    The imageInfo instance is a instance of a class that wraps TW_IMAGEINFO struct.

    best regards

    August 12, 2009 at 3:22 pm #24992 Reply
    dpenney
    Participant
    • Topics - 3
    • Replies - 66
    • Total Posts - 69

    Windows BMP images have the origin (point 0,0) at the bottom-left corner of the image. Most everything else has it at the top-left.

    A quick and easy solution is to write a negative length in the header. For example, if the image is 100 pixels long, set the length to -100. Most programs can handle that. Some interpret the length as an unsigned integer so a negative value looks like a very large positive value. Usually, these programs will report that there’s not enough memory to load the image.

    The other solution is to flip the pixels vertically so the origin is at the bottom-left.

    –

    August 13, 2009 at 8:08 am #24993 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Yes, now its ok, tank you. But theimage (under memory transfer mode)
    has some problem: the colors are not interpreted correctly and at certain resolution the image is streched.

    August 13, 2009 at 4:03 pm #24994 Reply
    dpenney
    Participant
    • Topics - 3
    • Replies - 66
    • Total Posts - 69

    Aren’t BMP’s a joy to work with? Not only are the rows bottom-up but the color sequence is BGR instead of the usual RGB. Obviously, to fix that you have to swap the red and blue channels for each pixel in the image.

    Aspect ratio distortion (i.e. stretching) could be caused by not setting the X and Y resolutions to the same value. Most DS’s do not support independent X and Y resolutions so another possibility is that you found a bug.

    –

    August 16, 2009 at 11:39 am #24995 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Tanks for the reply.
    Now i get image not stretched and in BGR format.
    Thare’s another problem now: for certains resolutions when i apply a little loop in order to convert from BGR to RGB the scanner produce an image with correct colors; with another resolution no.
    The routine is very simple: if i got a buffer (under TWRC_SUCCESS, o the last buffer under TWRX_XFERDONE) i do:


    for(int i=0; i {
    tmp=buf;
    buf
    =buf[i+2];
    buf[i+2]=tmp;
    }

    where buf is buffer memory.

    So i make a little test, and set all bytes to BLUE color, for example.
    So i wrote:


    for(int i=0; i {
    buf = 255;//Its in BGR format, for obtain a BLUE pixel
    buf[i+1]=0;
    buf[i+2]=0;
    }

    for all pixels in every buffer.
    What i expect is the image is all BLUE, unique color, but it’s not:
    I read (edited the image with GIMP) a ilne BLUE, another GREEN and the last RED, for all lines in the image.
    It’s strange.
    Can u help me about this?
    Why i change the resolution this strange behavior?
    I make a test with my scanner (BROTHER), the kodaki30 in simulation mode.
    Best regards

    August 16, 2009 at 3:59 pm #24996 Reply
    dpenney
    Participant
    • Topics - 3
    • Replies - 66
    • Total Posts - 69

    When the number of bytes per row is not evenly divisble by 3, you’re loop won’t work. Rewrite it to do one row at a time instead of the entire buffer in one pass.

    –

    August 17, 2009 at 10:19 am #24997 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Tank you, now it works!.
    Only last litttle problem: when in memory mode i set various values, the resulting image is always 72×72 dpi (openong it from gimp).
    Instead in native mode, when i set variuos resolutions, the dpi reflect the resolution i set previously.
    Any idea dpenney?
    The problem is that i never worked with images….
    Best regards

    August 17, 2009 at 2:54 pm #24998 Reply
    dpenney
    Participant
    • Topics - 3
    • Replies - 66
    • Total Posts - 69

    The resolution is specified in the header. The units are pixels per meter:

    const float INCHES_PER_METER = 39.3700787f;
    bmInfoHeader.biXPelsPerMeter = (int)((dpi * INCHES_PER_METER) + 0.5f);
    bmInfoHeader.biYPelsPerMeter = bmInfoHeader.biXPelsPerMeter;

    –

    August 18, 2009 at 1:21 pm #24999 Reply
    sdavi
    Participant
    • Topics - 4
    • Replies - 34
    • Total Posts - 38

    Hi depenney, tank you very much for all your support.
    Best regards

  • Author
    Posts
Viewing 11 posts - 1 through 11 (of 11 total)
Reply To: Memory transfer mode: desuming the header
Your information:




Quick Links

Service Providers
TWAIN Support Forums
Membership
Contact Us
Privacy Policy

Newsletter Signup

TWAIN Working Group Family

TWAIN Working Group
TWAIN Direct®
TWAIN Resources
TWAIN Certified Drivers
PDF/raster

  • Facebook
  • GitHub
  • LinkedIn
  • Vimeo

Recent Topics

  • EPSON V600 TWAIN and WIA on Windows 10
  • When and how to use WaitForEvents command ?
  • Problem enumerating list of installed scanners in windows server 2012
  • Failed to create TWAIN progress! Error code is 1260.
  • To get the list of scanners from javascript client side (browser)
  • Quarterly Newsletter
  • TWAIN Working Group Membership
  • Logo Usage
  • TWAIN License
  • Contact Us
Privacy Policy • Privacy Tools • Copyright © 2021 TWAIN Working Group • by iHwy, LLC • Log in

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.