August 9, 2009 at 6:42 pm #22520
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 regardsAugust 10, 2009 at 1:40 pm #24990
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
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.
Anyone can say me why the source transfer image data in that way?
Post my code in relevants parts:
/*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*/
//write last buffer into the file
//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.
The imageInfo instance is a instance of a class that wraps TW_IMAGEINFO struct.
best regardsAugust 12, 2009 at 3:22 pm #24992
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
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
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
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
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
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.
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 regardsAugust 16, 2009 at 3:59 pm #24996
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
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 regardsAugust 17, 2009 at 2:54 pm #24998
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
Hi depenney, tank you very much for all your support.
- This topic has 10 replies, 2 voices, and was last updated 11 years, 1 month ago by .
Viewing 11 posts - 1 through 11 (of 11 total)
Viewing 11 posts - 1 through 11 (of 11 total)