none
CImage::SetTransparentColorを行った場合の印刷について RRS feed

  • 質問

  • お世話になっております。

    VisualStudio2015で以下のようなコードを書いています。

    CImage::SetTransparentColorを指定して透過を行いましたが、

    画面は正しく表示されますが、印刷が出来ません。

    CImage::SetTransparentColorが無ければ問題なく行えます。

    何が問題か教えてください。

    よろしくお願い致します。

    CRect rc;
    GetClientRect(&rc);

    CImage img;
    img.SetTransparentColor(RGB(255, 255, 255));
    img.Load(_T("..\\test.jpg"));
    int iW = img.GetWidth();
    int iH = img.GetHeight();
    if (pDC->IsPrinting())
    {
      img.Draw(pDC->m_hDC, 0, 0, iW, iH);
    }
    else
    {
      int rH = rc.Height();
      int rW = (double)rH / (double)iH * (double)iW;
      img.Draw(pDC->m_hDC, 0, 0, rW, rH);
    }

    2016年11月22日 9:25

回答

  • CreateCompatibleDC( pDC->m_hDC )を行い、TransparentBlt(dcPrint.m_hDC,・・・)を行うとTransparentBltでエラーは起こりませんでしたが、印刷が出なかったです。

    TransparentBltで印刷できないとなると、CImageで透過色を指定した場合も印刷は難しそうですね。。

    ちなみに、こちらで印刷を確認したコードは下記のようなものでした。

    void CMFCPrintingView::OnDraw(CDC* pDC)
    {
    	HDC     hdcMem = CreateCompatibleDC(pDC->m_hDC);
    	HBITMAP hbmpMem = (HBITMAP)LoadImage(NULL, TEXT("C:\\work\\Sample.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    	HBITMAP hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, hbmpMem);
    	BITMAP	bm;
    	GetObject(hbmpMem, sizeof(BITMAP), &bm);
    	TransparentBlt(pDC->m_hDC, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 0, 0));
    	SelectObject(hdcMem, hbmpMemPrev);
    	DeleteObject(hbmpMem);
    	DeleteDC(hdcMem);
    }

    ※確認の為でしたのでエラー処理等は行っておりません。

    2016年11月25日 1:34

すべての返信

  • 回答ではないのですが、私の環境でも再現しましたので、CImage::Drawのコードを追ってみました。CImage::Drawでは、透過色をしていた場合と指定しなかった場合で処理が分かれていました。

    ・透過色を指定していた場合→TransparentBlt関数で描画が行われます

    ・透過色を指定しなかった場合→StretchBlt関数で描画が行われます
    ※アルファ値がある場合は、AlphaBlend関数で描画されるようです。

    そして、CImageの内部のデバイスコンテキストは CreateCompatibleDC( NULL ) で作成され、読み込んだイメージは、この内部のデバイスコンテキストから Draw の引数で渡されたデバイスコンテキストへ転送されます。

    StretchBlt関数は CreateCompatibleDC( NULL ) → pDC->m_hDC(プリンタのデバイスコンテキスト)への転送に成功しますが、

    TransparentBlt関数は、CreateCompatibleDC( NULL ) → pDC->m_hDCへの転送が失敗してうまく印刷ができませんでした。

    上記のことより、CImageで読み込んだ画像で透過色を指定する場合(他にPNGなどアルファ値を含む場合)は印刷への出力がうまく行えないことがあるようです。

    印刷時、TransparentBlt関数で、CreateCompatibleDC( pDC->m_hDC )  → pDC->m_hDCへの転送は成功しますので、イメージを読み込みの部分を記述してTransparentBlt 関数を使って印刷部分を自分で記述するか、あるいはGDI+でSetColorKeyを使って透過色の指定を行うのはどうでしょうか?

    [追伸]
    プリンタによって、TransparentBlt関数のCreateCompatibleDC( NULL ) → pDC->m_hDC転送で成功する環境もあるようです。brotherのモノクロレーザープリンタ(HL-2270DW)ではうまく印字できました。

    2016年11月22日 12:21
  • 回答ありがとうございます。

    透過色がある場合、TransparentBlt関数内でエラーが発生している件確認しました。

    CreateCompatibleDC( pDC->m_hDC )を行い、TransparentBlt(dcPrint.m_hDC,・・・)を行うとTransparentBltでエラーは起こりませんでしたが、印刷が出なかったです。

    GDI+を使用する件ですが。

    GDI+のDrawImageで印刷を行うと一部色が変色する」のタイトルで上げている問題もあるため、その方法も取りにくい状況です。

    プリンターによっては成功する場合もあるんですね。

    ありがとうございます。もう少しいろいろ試してみます。

    ちなみに、試しているプリンターは、RICOH MPC 3004です。

    • 編集済み sugi3 2016年11月24日 7:21
    2016年11月24日 7:18
  • CreateCompatibleDC( pDC->m_hDC )を行い、TransparentBlt(dcPrint.m_hDC,・・・)を行うとTransparentBltでエラーは起こりませんでしたが、印刷が出なかったです。

    TransparentBltで印刷できないとなると、CImageで透過色を指定した場合も印刷は難しそうですね。。

    ちなみに、こちらで印刷を確認したコードは下記のようなものでした。

    void CMFCPrintingView::OnDraw(CDC* pDC)
    {
    	HDC     hdcMem = CreateCompatibleDC(pDC->m_hDC);
    	HBITMAP hbmpMem = (HBITMAP)LoadImage(NULL, TEXT("C:\\work\\Sample.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    	HBITMAP hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, hbmpMem);
    	BITMAP	bm;
    	GetObject(hbmpMem, sizeof(BITMAP), &bm);
    	TransparentBlt(pDC->m_hDC, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 0, 0));
    	SelectObject(hdcMem, hbmpMemPrev);
    	DeleteObject(hbmpMem);
    	DeleteDC(hdcMem);
    }

    ※確認の為でしたのでエラー処理等は行っておりません。

    2016年11月25日 1:34
  • ありがとうございます。

    教えていただいた通りやってみたところ上手くいきました。

    下記のように記述したところ印刷まで出来ました。

    CImage img;
    img.Load(_T("..\\test.jpg"));
    int iW = img.GetWidth();
    int iH = img.GetHeight();
    
    HDC     hdcMem = CreateCompatibleDC(pDC->m_hDC);
    HBITMAP hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, img);
    BITMAP	bm;
    GetObject(img, sizeof(BITMAP), &bm);
    TransparentBlt(pDC->m_hDC, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 255, 255));
    
    SelectObject(hdcMem, hbmpMemPrev);
    DeleteDC(hdcMem);
    

    ありがとうございました。

    2016年11月25日 7:35