Impression d'un BITMAP
Le
atoub.michel
Bonjour,
Je suis en train de développer un Driver pour une imprimante. Et, je
souhaite imprimer une BITMAP.
Mais, je n'arrive pas à imprimer la BITMAP en couleur, la seule chose
qui s'imprime est un rectangle noir de la taille de l'image.
Ce que je fais :
1: je charge l'image avec LoadImage pour avoir un Handle de la Bitmap
2: je fais un GetObject pour obtenir la Bitmap
3: je crée ma structure BITMAPINFO
4: je crée mon compatibleDC pour l'écran en lui passant NULL comme
paramètre
5: je sélectionne mon objet SelectObject
6: je fais ma DIBColorTable
7: je rétablis le Bitmap d'origine avec SelectObject
8: je fais un StretchDIBits ou SetDIBitsToDevice pour afficher et
imprimer
/-- DEBUT CODE /
_DrawImage(std::string sImageFile, uint uiX, uint uiY, uint uiW /*=0*/,
uint uiH /*=0*/)
{
HBITMAP hbmpImage, hbmpMemOld;
BITMAP bmp; HDC hdcMem; // about the bitmap (size, color depth)
PBITMAPINFO info; // Structure for storing the DIB information, it will
be used by 'StretchDIBits()'
int nColors = 0; // Used to store the number of colors the DIB has
RGBQUAD rgb[256]; // Used to store the DIB color table
/* Etape 1 */
// The following line loads the bitmap from a file
hbmpImage = (HBITMAP) ::LoadImageA(NULL, sImageFile.c_str(),
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION|LR_LOADMAP3DCOLORS|LR_LOADFROMFILE);
if( ! hbmpImage)
return PRN_FRESULT(ERROR_BADPARAMETER, 1);
/* Etape 2 */
// Obtain information about 'hbmpImage' and store it in 'bmp'
::GetObject(hbmpImage, sizeof(BITMAP), (LPVOID) &bmp);
nColors = (1 << bmp.bmBitsPixel);
if(nColors > 256) nColors = 0; // This is when DIB is 24 bit.
// In this case there is not any color table information
/* Etape 3 */
// Now we need to know how much size we have to give for storing "info"
in memory.
// This involves the proper BITMAPINFO size and the color table size.
// Color table is only needed when the DIB has 256 colors or less.
info = CreateBitmapInfoStruct(hbmpImage);
// Now for 256 or less color DIB we have to fill the "info" color table
parameter
if(nColors >= 0 && nColors <= 256)
{
/* Etape 4 */
hdcMem = ::CreateCompatibleDC(NULL); // Creating an auxiliary
device context with screen
/* Etape 5*/
hbmpMemOld = (HBITMAP) ::SelectObject(hdcMem, hbmpImage); //
Select this bitmap in this DC:
/* Etape 6*/
::GetDIBColorTable(hdcMem, 0, nColors, rgb); // Obtaining the
color table information
// Now we pass this color information to "info"
for(int iCnt = 0; iCnt < nColors; ++iCnt)
{
info->bmiColors[iCnt].rgbRed = rgb[iCnt].rgbRed;
info->bmiColors[iCnt].rgbGreen =
rgb[iCnt].rgbGreen;
info->bmiColors[iCnt].rgbBlue = rgb[iCnt].rgbBlue;
}
/* Etape 7*/
// Rétablir le bitmap d'origine:
::SelectObject(hdcMem, hbmpMemOld);
}
/* Etape 8 */
// Stretching all the bitmap on a destination rectangle of size
(size_x, size_y)
// and upper left corner at (uiX, uiY)
if( (uiW == 0) && (uiH == 0) )
// To printer device
// m_hdcCurrent est le HDC de l'imprimante
::SetDIBitsToDevice(m_hdcCurrent,
uiX,
uiY,
info->bmiHeader.biWidth,
info->bmiHeader.biHeight,
0,
0,
0,
info->bmiHeader.biHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS);
else
// To printer device
::StretchDIBits(m_hdcCurrent,
uiX,
uiY,
uiW,
uiH,
0,
0,
bmp.bmWidth,
bmp.bmHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS,
SRCCOPY);
// This mode, DIB_RGB_COLORS indicate the color table are pure RGB
values
// The mode DIB_PAL_COLORS indicate the color table items are index to
the local palette items
//.. Delete les differents objets
}
/-- FIN CODE /
Je ne vois pas où le problème viendrait mais j'ai une piste sur le
fait qu'il faudrait deux HDC (un pour l'écran et un pour
l'imprimante), mais je ne suis pas sûr.
Le problème aussi est que j'ai fait un programme de tests et dans ce
programme simule une impression. Avec cette simulation, j'obtiens la
même chose que si j'imprime (un rectangle noir).
Merci de pouvoir m'aider
@+
Je suis en train de développer un Driver pour une imprimante. Et, je
souhaite imprimer une BITMAP.
Mais, je n'arrive pas à imprimer la BITMAP en couleur, la seule chose
qui s'imprime est un rectangle noir de la taille de l'image.
Ce que je fais :
1: je charge l'image avec LoadImage pour avoir un Handle de la Bitmap
2: je fais un GetObject pour obtenir la Bitmap
3: je crée ma structure BITMAPINFO
4: je crée mon compatibleDC pour l'écran en lui passant NULL comme
paramètre
5: je sélectionne mon objet SelectObject
6: je fais ma DIBColorTable
7: je rétablis le Bitmap d'origine avec SelectObject
8: je fais un StretchDIBits ou SetDIBitsToDevice pour afficher et
imprimer
/-- DEBUT CODE /
_DrawImage(std::string sImageFile, uint uiX, uint uiY, uint uiW /*=0*/,
uint uiH /*=0*/)
{
HBITMAP hbmpImage, hbmpMemOld;
BITMAP bmp; HDC hdcMem; // about the bitmap (size, color depth)
PBITMAPINFO info; // Structure for storing the DIB information, it will
be used by 'StretchDIBits()'
int nColors = 0; // Used to store the number of colors the DIB has
RGBQUAD rgb[256]; // Used to store the DIB color table
/* Etape 1 */
// The following line loads the bitmap from a file
hbmpImage = (HBITMAP) ::LoadImageA(NULL, sImageFile.c_str(),
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION|LR_LOADMAP3DCOLORS|LR_LOADFROMFILE);
if( ! hbmpImage)
return PRN_FRESULT(ERROR_BADPARAMETER, 1);
/* Etape 2 */
// Obtain information about 'hbmpImage' and store it in 'bmp'
::GetObject(hbmpImage, sizeof(BITMAP), (LPVOID) &bmp);
nColors = (1 << bmp.bmBitsPixel);
if(nColors > 256) nColors = 0; // This is when DIB is 24 bit.
// In this case there is not any color table information
/* Etape 3 */
// Now we need to know how much size we have to give for storing "info"
in memory.
// This involves the proper BITMAPINFO size and the color table size.
// Color table is only needed when the DIB has 256 colors or less.
info = CreateBitmapInfoStruct(hbmpImage);
// Now for 256 or less color DIB we have to fill the "info" color table
parameter
if(nColors >= 0 && nColors <= 256)
{
/* Etape 4 */
hdcMem = ::CreateCompatibleDC(NULL); // Creating an auxiliary
device context with screen
/* Etape 5*/
hbmpMemOld = (HBITMAP) ::SelectObject(hdcMem, hbmpImage); //
Select this bitmap in this DC:
/* Etape 6*/
::GetDIBColorTable(hdcMem, 0, nColors, rgb); // Obtaining the
color table information
// Now we pass this color information to "info"
for(int iCnt = 0; iCnt < nColors; ++iCnt)
{
info->bmiColors[iCnt].rgbRed = rgb[iCnt].rgbRed;
info->bmiColors[iCnt].rgbGreen =
rgb[iCnt].rgbGreen;
info->bmiColors[iCnt].rgbBlue = rgb[iCnt].rgbBlue;
}
/* Etape 7*/
// Rétablir le bitmap d'origine:
::SelectObject(hdcMem, hbmpMemOld);
}
/* Etape 8 */
// Stretching all the bitmap on a destination rectangle of size
(size_x, size_y)
// and upper left corner at (uiX, uiY)
if( (uiW == 0) && (uiH == 0) )
// To printer device
// m_hdcCurrent est le HDC de l'imprimante
::SetDIBitsToDevice(m_hdcCurrent,
uiX,
uiY,
info->bmiHeader.biWidth,
info->bmiHeader.biHeight,
0,
0,
0,
info->bmiHeader.biHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS);
else
// To printer device
::StretchDIBits(m_hdcCurrent,
uiX,
uiY,
uiW,
uiH,
0,
0,
bmp.bmWidth,
bmp.bmHeight,
bmp.bmBits,
info,
DIB_RGB_COLORS,
SRCCOPY);
// This mode, DIB_RGB_COLORS indicate the color table are pure RGB
values
// The mode DIB_PAL_COLORS indicate the color table items are index to
the local palette items
//.. Delete les differents objets
}
/-- FIN CODE /
Je ne vois pas où le problème viendrait mais j'ai une piste sur le
fait qu'il faudrait deux HDC (un pour l'écran et un pour
l'imprimante), mais je ne suis pas sûr.
Le problème aussi est que j'ai fait un programme de tests et dans ce
programme simule une impression. Avec cette simulation, j'obtiens la
même chose que si j'imprime (un rectangle noir).
Merci de pouvoir m'aider
@+

Poser une question

Les deux fonctions de base sont EnumPrinters() puis CreateDC().
--
Arnold McDonald (AMcD) - Help #49/2006
http://arnold.mcdonald.free.fr/
Une de mes vieilles fonctions, basée à 98% sur la KB186736 =>
BOOL PrintBitmap(HBITMAP hBitmap, int iWidth , int iHeight, int
nOrientation)
{
HBITMAP hbm, hBitmapOld;
HDC hdcPrinter;
HDC hdcMemory, hdcMem;
HDC hdcScreen;
DOCINFO di;
RECT rc;
DIBSECTION ds;
HPALETTE hPal;
BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bmp);
PRINTDLG pd;
ZeroMemory(&pd, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
PrintDlg(&pd);
hdcPrinter=pd.hDC;
DEVMODE *dm=(DEVMODE *)GlobalLock(pd.hDevMode);
dm->dmOrientation=nOrientation;
ResetDC(pd.hDC,dm);
GlobalUnlock(pd.hDevMode);
if (!hdcPrinter) return FALSE;
hdcScreen = GetDC(NULL);
hdcMem = CreateCompatibleDC(hdcScreen);
hBitmapOld = (HBITMAP)SelectObject(hdcMem, hBitmap);
hbm = Create24BPPDIBSection(hdcMem, bmp.bmWidth, bmp.bmHeight);
if (!hbm)
{
DeleteDC(hdcPrinter);
ReleaseDC(NULL, hdcScreen);
SelectObject(hdcMem, hBitmapOld);
DeleteDC(hdcMem);
MessageBox(NULL, "Error Creating DIB Section", "Error", MB_OK |
MB_ICONSTOP);
return FALSE;
}
hdcMemory = CreateCompatibleDC(hdcScreen);
SelectObject(hdcMemory, hbm);
hPal = GetSystemPalette();
if (hPal)
{
SelectPalette(hdcMem, hPal, FALSE);
RealizePalette(hdcMem);
SelectPalette(hdcMemory, hPal, FALSE);
RealizePalette(hdcMemory);
}
BitBlt(hdcMemory, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0,
SRCCOPY);
ZeroMemory(&di, sizeof(di));
di.cbSize = sizeof(di);
di.lpszDocName = "Bitmap Printing";
if (StartDoc(hdcPrinter, &di))
{
if (StartPage(hdcPrinter))
{
GetObject(hbm, sizeof(DIBSECTION), &ds);
StretchDIBits(hdcPrinter,
0, 0, iWidth, iHeight,
0, 0, bmp.bmWidth, bmp.bmHeight,
ds.dsBm.bmBits,
(LPBITMAPINFO)&ds.dsBmih,
DIB_RGB_COLORS,
SRCCOPY);
EndPage(hdcPrinter);
}
EndDoc(hdcPrinter);
}
DeleteDC(hdcPrinter);
DeleteDC(hdcMemory);
SelectObject(hdcMem, hBitmapOld);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);
DeleteObject(hbm);
if (hPal) DeleteObject(hPal);
}
Mais mon DC sur mon imprimante existe bien c'est "m_hdcCurrent". Il
n'est pas null pourtant, je ne comprends pas mais je recherche
toujours.
@+
Michel
Et tu le crées où et comment ce DC ?
--
Arnold McDonald (AMcD)
http://arnold.mcdonald.free.fr/
En fait, j'ai fais une fonciton NewPage où je le crée ainsi :
// internal printer variables
HDC m_hdcCurrent; // dans le Header
//---------- dans la fonction NewPage, cette fonction me permet en mode
simuler de faire une fenetre
// avec un "page" blanche (comme dans Paint) qui représente ma feuille
de papier.
m_hdcCurrent = ::CreateCompatibleDC(NULL);
// create the bitmap that will store the "page"
m_hbmpCurrent = ::CreateCompatibleBitmap(m_hdcCurrent, m_uiPageW,
m_uiPageH);
et en mode réel dans ma fonction PrintPage je fais :
// create a printer DC to spool
hdcPrinter = ::CreateDC(NULL, sDeviceName.c_str(), NULL, pdm);
// actually print
BitBlt(hdcPrinter, 0, -int(uiH), uiW, uiH, m_hdcCurrent, 0, -int(uiH),
SRCCOPY);
Voilà, je sais que c'est un peu compliqué mais je suis obligé de
suivre cette voie.
@+