Skip to content

Commit

Permalink
Merge pull request sakura-editor#683 from beru/BackImg_WIC
Browse files Browse the repository at this point in the history
Windows Imaging Component を使って背景画像を読み込み、透過描画対応
  • Loading branch information
beru authored Dec 8, 2018
2 parents 430583f + 814f306 commit c6df4e5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 62 deletions.
2 changes: 2 additions & 0 deletions sakura_core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ LIBS= \
-limagehlp \
-lshlwapi \
-lwinmm \
-lwindowscodecs \
-lmsimg32 \
-mwindows \
$(MYLIBS)

Expand Down
120 changes: 66 additions & 54 deletions sakura_core/doc/CEditDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#include <string.h> // Apr. 03, 2003 genta
#include <memory>
#include <OleCtl.h>
#include <wincodec.h>
#pragma comment(lib, "windowscodecs.lib")
#include <wrl.h>
#include "doc/CEditDoc.h"
#include "doc/logic/CDocLine.h" /// 2002/2/3 aroka
#include "doc/layout/CLayout.h" // 2007.08.22 ryoji 追加
Expand Down Expand Up @@ -317,61 +320,70 @@ void CEditDoc::SetBackgroundImage()
GetInidirOrExedir( &fullPath[0], &path[0] );
path = fullPath;
}
const TCHAR* ext = path.GetExt();
if( 0 != auto_stricmp(ext, _T(".bmp")) ){
HANDLE hFile = ::CreateFile(path.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE ){
return;
}
DWORD fileSize = ::GetFileSize(hFile, NULL);
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, fileSize);
if( hGlobal == NULL ){
::CloseHandle(hFile);
return;
}
DWORD nRead;
BOOL bRead = ::ReadFile(hFile, GlobalLock(hGlobal), fileSize, &nRead, NULL);
::CloseHandle(hFile);
hFile = NULL;
if( !bRead ){
::GlobalFree(hGlobal);
return;
}
::GlobalUnlock(hGlobal);
{
IPicture* iPicture = NULL;
IStream* iStream = NULL;
//hGlobalの管理を移譲
if( S_OK != ::CreateStreamOnHGlobal(hGlobal, TRUE, &iStream) ){
GlobalFree(hGlobal);
}else{
if( S_OK != ::OleLoadPicture(iStream, fileSize, FALSE, IID_IPicture, (void**)&iPicture) ){
}else{
HBITMAP hBitmap = NULL;
short imgType = PICTYPE_NONE;
if( S_OK == iPicture->get_Type(&imgType) && imgType == PICTYPE_BITMAP &&
S_OK == iPicture->get_Handle((OLE_HANDLE*)&hBitmap) ){
m_nBackImgWidth = m_nBackImgHeight = 1;
m_hBackImg = (HBITMAP)::CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, 0);
}
}
}
if( iStream ) iStream->Release();
if( iPicture ) iPicture->Release();
}
}else{
m_hBackImg = (HBITMAP)::LoadImage(NULL, path.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
}
if( m_hBackImg ){
BITMAP bmp;
GetObject(m_hBackImg, sizeof(BITMAP), &bmp);
m_nBackImgWidth = bmp.bmWidth;
m_nBackImgHeight = bmp.bmHeight;
if( 0 == m_nBackImgWidth || 0 == m_nBackImgHeight ){
::DeleteObject(m_hBackImg);
m_hBackImg = NULL;
}

using namespace Microsoft::WRL;
ComPtr<IWICImagingFactory> pIWICFactory;
HRESULT hr;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pIWICFactory));
if( FAILED(hr) ) return;
ComPtr<IWICBitmapDecoder> pDecoder;
hr = pIWICFactory->CreateDecoderFromFilename(
path.c_str(),
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder);
if( FAILED(hr) ) return;
ComPtr<IWICBitmapFrameDecode> pFrame;
hr = pDecoder->GetFrame(0, &pFrame);
if( FAILED(hr) ) return;
//WICPixelFormatGUID pixelFormat;
//hr = pFrame->GetPixelFormat(&pixelFormat);
//if( FAILED(hr) ) return;
ComPtr<IWICFormatConverter> pConverter;
pIWICFactory->CreateFormatConverter(&pConverter);
if( FAILED(hr) ) return;
hr = pConverter->Initialize(
pFrame.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeCustom);
if( FAILED(hr) ) return;
UINT width, height;
hr = pConverter->GetSize(&width, &height);
if( FAILED(hr) ) return;
BITMAPINFO bminfo = {0};
BITMAPINFOHEADER& bmih = bminfo.bmiHeader;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = (LONG)width;
bmih.biHeight = -(LONG)height;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
HDC hdcScreen = GetDC(NULL);
if( !hdcScreen ) return;
void *pvImageBits = NULL;
m_hBackImg = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
ReleaseDC(NULL, hdcScreen);
if( !m_hBackImg ) return;
UINT lineStride = 4 * width;
hr = pConverter->CopyPixels(
NULL,
lineStride,
lineStride * height,
(BYTE*)pvImageBits);
if( FAILED(hr) ){
::DeleteObject(m_hBackImg);
m_hBackImg = NULL;
}
m_nBackImgWidth = (int)width;
m_nBackImgHeight = (int)height;
}

/* 全ビューの初期化:ファイルオープン/クローズ時等に、ビューを初期化する */
Expand Down
2 changes: 1 addition & 1 deletion sakura_core/typeprop/CPropTypesWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ INT_PTR CPropTypesWindow::DispatchEvent(
case IDC_BUTTON_BACKIMG_PATH_SEL:
{
CDlgOpenFile::SelectFile(hwndDlg, GetDlgItem(hwndDlg, IDC_EDIT_BACKIMG_PATH),
_T("*.bmp;*.jpg;*.jpeg"), true, EFITER_NONE );
_T("*.bmp;*.jpg;*.jpeg;*.png"), true, EFITER_NONE );
}
return TRUE;
// From Here Sept. 10, 2000 JEPRO
Expand Down
22 changes: 16 additions & 6 deletions sakura_core/view/CEditView_Paint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "StdAfx.h"
#include <vector>
#include <limits.h>
#pragma comment(lib, "Msimg32.lib")
#include "view/CEditView_Paint.h"
#include "view/CEditView.h"
#include "view/CViewFont.h"
Expand Down Expand Up @@ -198,6 +199,8 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg)
#else
CTypeSupport cTextType(this,COLORIDX_TEXT);
COLORREF colorOld = ::SetBkColor(hdc, cTextType.GetBackColor());
MyFillRect(hdc, rcPaint);

const CTextArea& area = GetTextArea();
const CEditDoc& doc = *m_pcEditDoc;
const STypeConfig& typeConfig = doc.m_cDocType.GetDocumentAttribute();
Expand Down Expand Up @@ -279,20 +282,29 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg)
CMyRect rcBltAll;
rcBltAll.SetLTRB(INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
CMyRect rcImagePosOrg = rcImagePos;
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xFF;
bf.AlphaFormat = AC_SRC_ALPHA;
for(; rcImagePos.top <= nYEnd; ){
for(; rcImagePos.left <= nXEnd; ){
CMyRect rcBlt;
if( ::IntersectRect(&rcBlt, &rc, &rcImagePos) ){
::BitBlt(
int width = rcBlt.right - rcBlt.left;
int height = rcBlt.bottom - rcBlt.top;
::AlphaBlend(
hdc,
rcBlt.left,
rcBlt.top,
rcBlt.right - rcBlt.left,
rcBlt.bottom - rcBlt.top,
width,
height,
hdcBgImg,
rcBlt.left - rcImagePos.left,
rcBlt.top - rcImagePos.top,
SRCCOPY
width,
height,
bf
);
rcBltAll.left = t_min(rcBltAll.left, rcBlt.left);
rcBltAll.top = t_min(rcBltAll.top, rcBlt.top);
Expand Down Expand Up @@ -336,8 +348,6 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg)
if( y3 < y4 ){
rcFill.SetLTRB(x1,y3, x4,y4); MyFillRect(hdc, rcFill);
}
}else{
MyFillRect(hdc, rc);
}
::SetBkColor(hdc, colorOld);
#endif
Expand Down
2 changes: 1 addition & 1 deletion tests/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ elseif (MINGW)
list (TRANSFORM ALL_O REPLACE "\\.(cpp|rc)$" ".o")
target_link_libraries (${project_name} PRIVATE ${ALL_O})
endif ()
target_link_libraries (${project_name} PRIVATE winspool ole32 oleaut32 uuid comctl32 imm32 mpr imagehlp shlwapi winmm)
target_link_libraries (${project_name} PRIVATE winspool ole32 oleaut32 uuid comctl32 imm32 mpr imagehlp shlwapi winmm windowscodecs msimg32)

0 comments on commit c6df4e5

Please sign in to comment.