Link to home
Start Free TrialLog in
Avatar of rw8
rw8

asked on

Printing a high resolution image

Hi ! I have problem in printing high resolution images.
I'm trying to print a A4 Size 300dpi bitmap image to some different colour printers. However, I never print anything out succesfully. (The printer does not printout anything at all). The printers I used are SONY UDP-8800 (a professional photo printer with 30mb RAM on board), HP PhotoSmart (an ink-jet printer with NO on board memory).
If I lower the original image resolution to say 100dpi, then I can printout the image successfully. Or if I make the size of the original image smaller and then enlarge it to A4 output size.. then it's ok too..
However, if I use photoshop to print the original high resolution A4 image, I can print it out properly....
Can anyone tell me why is it and how to solve it?

I'm using the following code in my printing function to load and print the image:


.
.
.
CString m_sBitmap="c:\\hires.bmp";
CBitmap m_bmpBitMap;
HBITMAP hbitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),m_sBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if(hbitmap)
{
      if(m_bmpBitMap.DeleteObject())
            m_bmpBitMap.Detach();
      m_bmpBitMap.Attach(hbitmap);
}
BITMAP bm;
m_bmpBitMap.GetBitmap(&bm);
CDC dcMem;
dcMem.CreateCompatibleDC(&dcPrinter);
CBitmap *pOldBitmap=(CBitmap*)dcMem.SelectObject(m_bmpBitMap);
dcPrinter.StretchBlt(0,0,pageWidth,pageHeight,&dcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);

My friend has written another Borland C Builder application to do the same job and he got the same problem.
Avatar of rw8
rw8

ASKER

I tried to print the hi resolution image using the following applications but none of them can print it out successfully: Microsoft Word (office 95), ACDSee Ver 3.0 Trial..etc

Do you know if the load of the imageinto your m_bmpBitMap worked ok?

If so, try printing to the printer in bands (ie. don't StretchBlt the whole thing in oe go, but do strips instead)

If not, then windows is simply not able to find a big enough lump of contiguous memory, or there is some internal limit to LoadImage.  Try using the OleLoadPicture API instead.  This has the advantage of also being able to directly load JPG and GIF images.

Avatar of rw8

ASKER

it seems I can load the image successfully..  since I also tried to use some other methods to load the image and then save it to some other files and I can get the output file succesfully.,. btw,  how to print it in bands? I tried to use the function ExtEscape to do banding... but I always got a return value of 0 when calling this function... got any idea about it?
Just make multiple class to StretchBlt.

eg. instead of
dcPrinter.StretchBlt(
  0,0,pageWidth,pageHeight,
  &dcMem,
  0,0,bm.bmWidth,bm.bmHeight,
  SRCCOPY);

try something like this...

int pageBandHeight = pageHeight/4;
int bmBandHeight = bm.bmHeight/4;
for (i = 0; i < 4; i++) {
  dcPrinter.StretchBlt(
    0,i*pageBandHeight,
    pageWidth,pageBandHeight,
    &dcMem,
    0,i*bmBandHeight,
    bm.bmWidth,bmBandHeight,
    SRCCOPY);
}

NOTE: this assumes the hieght are evenly divisible by 4, but you should get the idea.


Avatar of rw8

ASKER

no sorri.. still doesn't work..
I tried use CDC::Escape() to do banding but it does not help since my printers (hardware) does not support banding.. (i.e. banding= no banding)
Don't use the Escape function.  And try more bands .. maybe 4 is not enough.
Avatar of rw8

ASKER

it seems to me that no matter how many pieces I divide the image into... if the total size exceeds 16Mb.. then it doesn't work...
btw, the printer I'm using are a bit old .. (I think they are 3-4 yrs old).. is it possible that the driver does not support printing that large image?
Since if I use some custom image processing library to print to the printer directly.. (bypass the printer driver).. then I can printout the image.. however, the quality is very bad..
Avatar of rw8

ASKER

Does not work. It seems that the problem comes from the printer driver. I tried to use some newer colour printers and it is ok.
Hi,

I've had the same problem before. The problem is that the StretchBlt function does not work on very large images. This is only a problem for 95 and 98. In the end I had to print my image in bands. This involved multiple calls to the StretchBlt function.

Here is what MSDN says on the issue:

BUG: StretchBlt()/StretchDIBits() Fail with Very Large Stretch
ID: Q111865

 
3.00 3.10 WINDOWS kbprg kbbuglist
--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Windows Software Development Kit (SDK) for Windows versions 3.0 and 3.1

--------------------------------------------------------------------------------


SYMPTOMS
If the stretching factor is large, for example, when stretching from a very small to a large height, StretchDIBits() and StretchBlt() may return zero (0) and display nothing. The same bitmap with a smaller stretch is displayed correctly.



CAUSE
Most display drivers do not implement their own StretchBlt() or StretchDIBits() so GDI must simulate these calls. Part of the GDI simulation involves allocating temporary work buffers, which are limited to 64K. If the size of the work buffer is calculated to be greater than 64K, then the height of the source and destination rectangles are halved until they are less than 64K. The problem is that if GDI must continue to divide the height by two (2) to get a buffer less than 64K, the source or destination height could eventually reach one scan line. At this point, the call fails because it cannot break up a scan line into subunits.

StretchBlt() and StretchDIBits() are not designed to provide unlimited stretching. However, they may fail a bit more prematurely than their design limitation.



RESOLUTION
If StretchBlt() or StretchDIBits() fails on a large stretch, an application can divide up the source bitmap, stretch the pieces individually, and position them correctly once stretched. Another alternative is to do a smaller stretch. There is no formula to determine exactly what bitmaps will fail at what stretch size.



STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.



MORE INFORMATION
To reproduce the problem, create a bitmap approximately 2048 pixels wide by 16 pixels high. Then, display the bitmap with the DIBVIEW sample from the Windows 3.1 SDK. Choose Stretch To Window from DIBVIEW's Options menu, so that the bitmap is stretched according to the size of the client window. When the height is more than about 200 pixels, the bitmap will not be displayed.

Additional query words: buglist3.00 buglist3.10 3.00 3.10 fail zoom


Keywords          : kbWinOS310 kbDSupport kbWinOS300 kbSDKWin16
Version           :
Platform          :
Issue type        : kbbug
 


Last Reviewed: July 14, 1999
© 1999 Microsoft Corporation. All rights reserved. Terms of Use.
 



--------------------------------------------------------------------------------
Send feedback to MSDN.Look here for MSDN Online resources
Avatar of rw8

ASKER

But why is that I have no problem in printing those big images when I use some late model printers? (e.g. Epson PhotoStylus 700)

Avatar of rw8

ASKER

Mr DaveB, can you also tell me how you print your image in bands? I tried using "ExtEscape" to do banding but it does not help me.
I have alreaduy suggested printing in bands and rw8 says that this doesn't help him.

That should not be proposed as an answer, because a) it is exactly the same what I already proposed and b) it doesn't explain the problem as it appears to be printer specific.

The problem could be the page size that is being blt'd to.  Did you get teh size from the printer deveice capabilities?
Avatar of rw8

ASKER

Yes. I can get the print page size. (and remember that I cannot printout those high resolution images using some other commerical software as well)
I cannot verify what MrDaveB said is correct or not (he said the problem is due to the limitation of win95/98) since I can't find any WINNT drivers for the printers I'm using (that cannot print out the high resolution images).
Eh ??? .. this is the opposite of what you said initially

"However, if I use photoshop to print the original high resolution A4 image, I can print it out properly....
Can anyone tell me why is it and how to solve it?

Please verify: Can you print successfully with all / some / no other (commercial) software?

BTW: Does your StretchBlt function return an OK status ?
Avatar of rw8

ASKER

sorry that I didn't explain very clearly.. I CAN print out the high resolution A4 image using Photoshop. (but only photoshop).. then I tried to print the same image using other commercial software (like ACDsee  and MS Word) and it didn't work.

I'll tell you the return value of "StretchBlt" tomorrow since I have deleted my project (by mistake) and I'm trying to rebuild the project from my backup files right now :(
Avatar of rw8

ASKER

I found that I have problem in loading big BMP images. I tried to load a bitmap image with resolution around 3000*2000 pixels (24 bit colour) .. and it seems that the image cannot be loaded at all.. (therefore can't verify whether the stretchBlt function works or not) and then when I decrease the image to a much smaller size .. then it's ok.. (and the stretchBlt function returns ok.
Anyway, I copied my sample code which I'm using to test printing images... maybe you guys can copy it and see what's wrong :P


void CBandingDlg::OnButton1()
{

      CPrintDialog dlg(FALSE);
      if(dlg.DoModal()==IDOK)
      {
            
      
            HDC hdcPrinter = dlg.CreatePrinterDC();
            if (hdcPrinter == NULL)
            {
                  MessageBox(_T("Sorry. You don't have a printer!"));
                  return;
            }
            else
            {
                  CDC dcPrinter;
                  dcPrinter.Attach(hdcPrinter);
                  DOCINFO docinfo;
                  memset(&docinfo, 0, sizeof(docinfo));
                  docinfo.cbSize = sizeof(docinfo);
                  docinfo.lpszDocName = _T("Banding");
                  
                  
                  HIGEAR hiResImage,hi1,hi2;                  
                  StartDoc(hdcPrinter,&docinfo);
                  StartPage(hdcPrinter);

                                                      
      
                  BOOL bError=FALSE;
                  RECT rect;
                  int xPage,yPage;
                  xPage=GetDeviceCaps(hdcPrinter,HORZRES);
                  yPage=GetDeviceCaps(hdcPrinter,VERTRES);

                  CString m_sBitmap="c:\\hires.bmp";
            CBitmap m_bmpBitMap;
            HBITMAP hbitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),m_sBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);

            if(hbitmap)
            {
                        if(m_bmpBitMap.DeleteObject())
                              m_bmpBitMap.Detach();
                m_bmpBitMap.Attach(hbitmap);
            }
            BITMAP bm;
            m_bmpBitMap.GetBitmap(&bm);
            CDC dcMem;
            dcMem.CreateCompatibleDC(&dcPrinter);
            CBitmap *pOldBitmap=(CBitmap*)dcMem.SelectObject(m_bmpBitMap);


                  int pageBandHeight = yPage/4;
            int bmBandHeight = bm.bmHeight/4;
                  int i;
            for (i = 0; i < 4; i++)
                  {
                        dcPrinter.StretchBlt(
                        0,i*pageBandHeight,
                        xPage,pageBandHeight,
                        &dcMem,
                0,i*bmBandHeight,
                bm.bmWidth,bmBandHeight,SRCCOPY);
            }

                  EndPage(hdcPrinter);
                  EndDoc(hdcPrinter);
                  DeleteDC(hdcPrinter);

            }
            return;
      }
}
So does this mean you don't know whether or not the printing works, because you cannot load in an image big enough to print.

In that case, the code above isn't going to tell us much.  It is quite likely that the printing is working ok .. just that there is nothing to print.

Is that indeed the case?

NOTE: There are limits to the size of bitmap that can be read .. you need  conigutous memory for a bitmap, and 3000x2000x24bit = 18,000,000 bytes ~= 18MB.  That's a lot of contiguous memory to find.

Have you tried checking the success of LoadImage.  If it fails, call GetLastError to find out why.


Avatar of rw8

ASKER

Since I found that the value o hbitmap is 0x000000 after LoadImage.. so I added a line
DWORD a=GetLastError() immediately after the line:
HBITMAP
                   hbitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),m_sBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);

and a is equal is 0 ..  (which means LoadImage was successful??)


One more thing is that I was not using LoadImage, StretchBlt..etc to load and print the image at first.. I was using an image library from Accusoft to do these jobs. and I'm sure the image was loaded successfully. And when I use Accusoft to print it out.. I cannot get the printout as well.. however, there is an option in accusoft's print function so that I can choose to NOT use the printer's driver and ask accusoft to deal with the printing process itself... in this case, I can printout the high resolution image.. BUT the image quality is very very poor..

Are you using Win95/98 ?  If so, you won't get error codes because Win95/98 doesn't support GetlastError for most GDI (and other) functions.

I imagine that the Accusoft printing is adjusting the resolution so that it fits.

Also, it would be interesting to try using OleLoadPicture instead of LoadImage, as this may work correctly.

Have you tried using another printer driver for that same brand (but maybe for a less capable model).  That might help.
Avatar of rw8

ASKER

1. Yes. I'm using Win95/98 to get the error msg. Actually I have tried to use WinNT to load the image and it was loaded successfully. however, the printers I'm using do not have any NT driver at all, so I cannot test the printing under NT.


2.This is what the Accusoft help file says about it's print function:
IG_print_image ( HIGEAR hIGear, BOOL bDirectToDriver );

This function prints a HIGEAR image to the current default printer (or prints only its image rectangle, if you have called IG_image_rect_set()for this image).  Argument bDirectToDriver, when TRUE, instructs ImageGear to send the image’s DIB directly to the printer’s device driver.  In this case the entire procedure has been placed in the hands of the driver.  If your printer has special capabilities such as color, and if the driver supports these, then your image can be printed with these features.
 
So if I set bDirectToDriver=false.. then it can print.


3. I did try to use OleLoadPicture to load the image.. but since my programming skill is limited.. I can't figure out how to call this function :P
It's not TOO tricky once you manage to get a stream that corresponds to your file.
Avatar of rw8

ASKER

Sorry.. I'm a bit dumb.. can't make it work.. (I haven't do any OLE programming b4)
is it easy for u to show me how to use it?
ASKER CERTIFIED SOLUTION
Avatar of RONSLOW
RONSLOW

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rw8

ASKER

Band printing doesn't help and RONSLOW did suggested this to me already
Avatar of rw8

ASKER

Comment accepted as answer
Avatar of rw8

ASKER

Thanx Ronslow. I found the problem really comes from the printer driver. After I obtained the latest version printer driver from the manufacturer, it solved the problem automatically.
That's good .. couldn't think of anything else to explain it :-)