- ホーム
- GDI+
- CBのbitmapをリサイズしてCBに書き戻す(その1)
クリップボードのbitmapをリサイズしてクリップボードに書き戻す(テンポラリファイル使用版)
テンポラリファイル不使用版を作成できたので、不必要であるが、
画像をADODB.Stream経由で読込む事例として残しておきます
Public Enum InterpolationMode ' 補間方法
InterpolationModeInvalid = -1
InterpolationModeDefault = 0
InterpolationModeLowQuality = 1
InterpolationModeHighQuality = 2
InterpolationModeBilinear = 3
InterpolationModeBicubic = 4
InterpolationModeNearestNeighbor = 5
InterpolationModeHighQualityBilinear = 6
InterpolationModeHighQualityBicubic = 7
End Enum
Private Type GdiplusStartupInput
GdiplusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type PICTDESC
cbSizeofStruct As Long
picType As Long
hbitmap As Long
hpal As Long
unused_wmf_yExt As Long
End Type
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Const PICTYPE_BITMAP = 1
Private Const INVALID_HANDLE_VALUE = -1
Private Const GENERIC_WRITE = &H40000000
Private Const GENERIC_READ As Long = &H80000000
Private Const CREATE_ALWAYS = &H2
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const UnitWorld = 0 ' World coordinate (non-physical unit)
Private Const UnitDisplay = 1 ' Variable -- for PageTransform only
Private Const UnitPixel = 2 ' Each unit is one device pixel.
Private Const UnitPoint = 3 ' Each unit is a printer's point, or 1/72 inch.
Private Const UnitInch = 4 ' Each unit is 1 inch.
Private Const UnitDocument = 5 ' Each unit is 1/300 inch.
Private Const UnitMillimeter = 6 ' Each unit is 1 millimeter.
Private Const PixelFormatIndexed As Long = &H10000 ' Indexes into a palette
Private Const PixelFormatGDI As Long = &H20000 ' Is a GDI-supported format
Private Const PixelFormatAlpha As Long = &H40000 ' Has an alpha component
Private Const PixelFormatPAlpha As Long = &H80000 ' Pre-multiplied alpha
Private Const PixelFormatExtended As Long = &H100000 ' Extended color 16 bits/channel
Private Const PixelFormatCanonical As Long = &H200000
Private Const PixelFormatUndefined As Long = 0
Private Const PixelFormatDontCare As Long = 0
'追加分 クリップボード操作
Private Const CF_BITMAP As Long = 2
Private Const CF_DIB = 8
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ByRef ppstm As Any) As Long
Private Const GMEM_MOVEABLE As Long = &H2&
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal pDest As Long, ByVal pSource As Long, ByVal dwLength As Long)
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
ByVal lpszName As String, ByVal dwAccess As Long, _
ByVal dwShareMode As Long, ByVal lpsa As Long, _
ByVal dwCreate As Long, ByVal dwAttrsAndFlags As Long, _
ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WriteFile Lib "kernel32" ( _
ByVal hFile As Long, ByRef lpBuffer As Any, _
ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, _
ByVal lpOverlapped As Long) As Long
Private Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GetClipboardData Lib "user32" ( _
ByVal wFormat As Long) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function EmptyClipboard Lib "user32" () As Long
Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
'GDI+開始
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, pInput As GdiplusStartupInput, _
pOutput As Any) As Long
'GDI+終了
Private Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal token As Long)
'デバイスコンテキストからGraphicsを生成
Private Declare Function GdipGetImageGraphicsContext Lib "gdiplus" (ByVal image As Long, graphics As Long) As Long
'Graphics削除
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
'補間モード設定
Private Declare Function GdipSetInterpolationMode Lib "gdiplus" (ByVal graphics As Long, _
ByVal nInterpolationMode As InterpolationMode) As Long
'Image削除
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
'Imageの寸法取得
Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As Long
Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As Long
'Graphicsのサイズに合わせてImage描画
Private Declare Function GdipDrawImageRectI Lib "gdiplus" (ByVal graphics As Long, ByVal image As Long, _
ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long) As Long
'ファイルからBitmap取得
Private Declare Function GdipCreateBitmapFromFile Lib "gdiplus" (FileName As Any, bitmap As Long) As Long
'GraphicsからBitmap取得
Private Declare Function GdipCreateBitmapFromGraphics Lib "gdiplus" (ByVal Width As Long, ByVal Height As Long, _
ByVal Target As Long, bitmap As Long) As Long
'BitmapをHBITMAPに変換、クリップボードへの貼り付けに必要
Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long, hbmReturn As Long, _
ByVal background As Long) As Long
'OleStdPictureの生成
Private Declare Function OleCreatePictureIndirect Lib "olepro32" (lpPictDesc As PICTDESC, riid As GUID, _
ByVal fOwn As Long, lplpvObj As Any) As Long
'Objectの削除
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function GdipCreateSolidFill Lib "gdiplus.dll" (ByVal pColor As Long, ByRef brush As Long) As Long
'塗りつぶし四角形を描画
Private Declare Function GdipFillRectangle Lib "gdiplus.dll" (ByVal graphics As Long, ByVal brush As Long, ByVal X As Single, ByVal Y As Single, ByVal nWidth As Single, ByVal nHeight As Single) As Long
'GDI+のブラシ削除
Private Declare Function GdipDeleteBrush Lib "gdiplus.dll" (ByVal brush As Long) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" ( _
ByVal hdc As Long, graphics As OLE_HANDLE) As Long
'Streamからイメージ生成
Private Declare Function GdipLoadImageFromStream Lib "gdiplus" _
(ByVal stm As Long, _
ByRef img As OLE_HANDLE) As Long
Sub test()
Dim lngRet As Long
lngRet = SaveClipboardDIB("c:\temp.bmp")
Call LoadPictureScaled2("c:\temp.bmp", Range("a2").Value)
Kill "c:\temp.bmp" 'GdipCreateBitmapFromFileだとファイルがロックされてしまう
ActiveSheet.Paste
End Sub
'ファイルロックを防ぐため、streamからの読込に変更
'http://www.vb-user.net/junk/replySamples/2007.10.21.12.01/DrawFromStream.txt
Private Sub LoadPictureScaled2( _
ByVal FileName As String, _
Optional ByVal outputHeight As Long = 240, _
Optional ByVal InterpolationMode As InterpolationMode = InterpolationModeBilinear _
)
Dim IID_IDispatch As GUID
Dim pd As PICTDESC
Dim udtInput As GdiplusStartupInput
Dim hBmp As Long
Dim lngToken As Long
Dim pGraphics As Long
Dim pSrcBmp As Long
Dim pDstBmp As Long
Dim lngWidth As Long
Dim lngHeight As Long
Dim lngStatus As Long
Dim hBrush As Long
Dim aspectRatio As Double
Dim bin() As Byte
Dim size As Long
Dim ptr As Long
Dim stm As Object
Dim ret As Long
Dim ghMem As Long
Dim gImg As OLE_HANDLE
Const adTypeBinary As Long = 1
Const adReadAll As Long = -1
' 初期化
udtInput.GdiplusVersion = 1
If GdiplusStartup(lngToken, udtInput, ByVal 0&) <> 0 Then
Exit Sub
End If
'ADODBでバイナリーで読み込んだStreamから画像生成
With CreateObject("ADODB.Stream")
.Type = adTypeBinary
.Open
.LoadFromFile FileName
bin = .Read(adReadAll)
.Close
End With
size = UBound(bin) + 1
ghMem = GlobalAlloc(GMEM_MOVEABLE, size)
ptr = GlobalLock(ghMem)
RtlMoveMemory ptr, VarPtr(bin(0)), size
ret = GlobalUnlock(ghMem)
ret = CreateStreamOnHGlobal(ghMem, 1, stm)
ret = GdipLoadImageFromStream(ObjPtr(stm), pSrcBmp)
Set stm = Nothing
' 元画像サイズの取得
GdipGetImageWidth pSrcBmp, lngWidth
GdipGetImageHeight pSrcBmp, lngHeight
aspectRatio = lngWidth / lngHeight
' サイズの変更
lngHeight = outputHeight
lngWidth = CLng(outputHeight * aspectRatio)
If GdipGetImageGraphicsContext(pSrcBmp, pGraphics) = 0 Then
' コピー先Bitmap作成
lngStatus = GdipCreateBitmapFromGraphics(lngWidth, lngHeight, pGraphics, pDstBmp)
GdipDeleteGraphics pGraphics
If lngStatus = 0 Then
' コピー用Graphics作成
If GdipGetImageGraphicsContext(pDstBmp, pGraphics) = 0 Then
' 補間方法の設定
GdipSetInterpolationMode pGraphics, InterpolationMode
'縁が出来てしまうので白で塗りつぶしておく2010/2/5
GdipCreateSolidFill &HFFFFFFFF, hBrush
GdipFillRectangle pGraphics, hBrush, 0, 0, lngWidth, lngHeight
GdipDeleteBrush hBrush
' イメージのコピー
GdipDrawImageRectI pGraphics, pSrcBmp, 0, 0, lngWidth, lngHeight
GdipDeleteGraphics pGraphics
' GDIのビットマップ作成
GdipCreateHBITMAPFromBitmap pDstBmp, hBmp, 0
End If
GdipDisposeImage pDstBmp
End If
End If
GdipDisposeImage pSrcBmp
GdiplusShutdown lngToken
If hBmp = 0 Then Exit Sub
'画像をクリップボードにコピー
If OpenClipboard(0) <> 0 Then
EmptyClipboard
SetClipboardData CF_BITMAP, hBmp
CloseClipboard
End If
End Sub
'クリップボードの画像(DIB情報)をBMP形式で保存
Public Function SaveClipboardDIB(ByVal sFileName As String) As Long
Dim bmi As BITMAPINFOHEADER
Dim bmh(0 To 7) As Integer
Dim hFile As Long, iWritten As Long
Dim hglb As Long, iMemSize As Long
Dim lpBuffer As Long, iDIBSize As Long
Dim ret As Long
Dim i As Long
'On Error GoTo ErrorHandler1
'クリップボードのオープン
If OpenClipboard(0) = 0 Then Exit Function
'DIBのメモリハンドルを取得
hglb = GetClipboardData(CF_DIB)
If hglb = 0 Then GoTo exit_CloseClipboard
'グローバルメモリのロック
lpBuffer = GlobalLock(hglb)
If lpBuffer = 0 Then GoTo exit_CloseClipboard
If lpBuffer < 0 Then GoTo exit_GlobalUnlock
'グローバルメモリのサイズのチェック
iMemSize = GlobalSize(hglb)
If iMemSize > 10000000 Then GoTo exit_GlobalUnlock
If iMemSize < 16 Then GoTo exit_GlobalUnlock
'BITMAPINFOHEADERの取得
MoveMemory bmi, ByVal lpBuffer, 4
MoveMemory bmi, ByVal lpBuffer, bmi.biSize
iDIBSize = iMemSize
'BITMAPFILEHEADERの作成
bmh(0) = &H4D42
i = 14 + iDIBSize
MoveMemory bmh(1), i, 4
i = 14 + bmi.biSize '
MoveMemory bmh(5), i, 4
'ファイルの作成
hFile = CreateFile(sFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0)
ret = WriteFile(hFile, bmh(0), 14, iWritten, 0)
ret = WriteFile(hFile, ByVal lpBuffer, iDIBSize, iWritten, 0)
If ret = 0 Then GoTo exit_CloseFile
ret = CloseHandle(hFile)
If ret = 0 Then GoTo exit_GlobalUnlock
hFile = 0
ret = GlobalUnlock(hglb)
If ret <> 0 Then GoTo exit_CloseClipboard
hglb = 0
ret = CloseClipboard()
Exit Function
exit_CloseFile:
ret = CloseHandle(hFile)
hFile = 0
exit_GlobalUnlock:
ret = GlobalUnlock(hglb)
hglb = 0
exit_CloseClipboard:
ret = CloseClipboard()
Exit Function
exit_Function:
Exit Function
ErrorHandler1:
If (hFile <> 0) And (hFile <> INVALID_HANDLE_VALUE) Then ret = CloseHandle(hFile)
If hglb Then ret = GlobalUnlock(hglb)
ret = CloseClipboard()
Exit Function
End Function