将旋转和颜色调整应用于GDI DeviceContext会导致颜色重置

时间:2011-09-01 22:25:56

标签: vb.net gdi

我正在使用API​​调用来转换Bitmap对象。我有各种物理变换(旋转,翻转,缩放,位移)以及一些颜色调整(反转,亮度和对比度)

除了将旋转或剪切变换与颜色调整结合使用时,一切正常。在这种情况下,颜色会恢复为原始图像。

这个问题的有趣之处在于它似乎依赖于XForm矩阵中的非对角线因素(下面的eM12和eM21)。例如,这是旋转矩阵:

Public Sub RotateClockwise(Radians As Single)
    With XFormMatrix
        .eM11 = Cos(Radians)
        .eM12 = Sin(Radians)
        .eM21 = -Sin(Radians)
        .eM22 = Cos(Radians)
        .eDx = 0
        .eDy = 0
    end with
end sub

每当eM12或eM21非零时,我的颜色就会丢失!例如,剪切变换会发生同样的问题:

Public Sub Shear(ShearFactorX As Single, ShearFactorY As Single)
    With XFormMatrix
        .eM11 = 1
        .eM12 = ShearFactorX
        .eM21 = ShearFactorY
        .eM22 = 1
        .eDx = 0
        .eDy = 0
    End With
End Sub

这是我应用转换并设置颜色调整

的子(缩写)
Private Declare Function CreateCompatibleDC Lib "GDI32.dll" (ByVal hDC As Long) As Long
Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, ByVal lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
Private Declare Function SelectObject Lib "GDI32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function SetWorldTransform Lib "gdi32" (ByVal hDC As Long, ByRef lpXform As xForm) As Long
Private Declare Function SetColorAdjustment Lib "GDI32.dll" (ByVal hDC As Long, ByRef lpCA As ColorAdjustment) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long

Private Sub TransformAndDraw()
'Initialise objects
BufferDC = CreateCompatibleDC(0)
BgBuffer = CreateDIBSection(hDC:=BufferDC, pBitmapInfo:=bmi, un:=DIB_RGB_COLORS, lplpVoid:=0&, handle:=0&, dw:=0&)
SelectObject BufferDC, BgBuffer

'Define the transformation matrices
SetWorldTransform hDC:=BufferDC, lpXform:=XFormMatrix

' Apply this colour adustment to the Buffer DC
SetColorAdjustment hDC:=BufferDC, lpCA:=NewAdjust

'load picSource into the Buffer and apply scaling factor
    StretchBlt hDC:=BufferDC, _
               x:=0, _
               y:=0, _
               nWidth:=srcBmp.bmWidth * xsize, _
               nHeight:=srcBmp.bmHeight * xsize, _
               hSrcDC:=srcHDC, _
               xSrc:=0, _
               ySrc:=0, _
               nSrcWidth:=srcBmp.bmWidth, _
               nSrcHeight:=srcBmp.bmHeight, _
               dwRop:=vbSrcCopy

'Paint the UserControl surface with the Buffer

'reset and delete objects
End Sub

总结一下我的问题:我在某些方面可以同时使用 SetWorldTransform SetColorAdjustment 对我的非对角线因素使用非零值XForm转型?

1 个答案:

答案 0 :(得分:0)

好的,我找到了解决方案。我将物理变换和颜色调整分成两个单独的StretchBlt调用。在此期间,我重置了Image-Buffer中的Xform矩阵,使其在颜色调整期间不存在。

在第一次调用中,外部图像源被加载到缓冲区中并根据Xform矩阵进行拉伸。 在第二次调用中,缓冲区被绘制到自身上以便应用颜色调整。

Private Sub TransformAndDraw()
    'Initialise objects
    BufferDC = CreateCompatibleDC(0)
    BgBuffer = CreateDIBSection(hDC:=BufferDC, pBitmapInfo:=bmi, un:=DIB_RGB_COLORS, lplpVoid:=0&, handle:=0&, dw:=0&)
    SelectObject BufferDC, BgBuffer

    'extract the original transform-settings
    OldGraphicsMode = SetGraphicsMode(hDC:=BufferDC, iMode:=GM_ADVANCED)
    GetWorldTransform hDC:=BufferDC, lpXform:=OldMatrix
    ' Get the current (default) colour adjustment
    OldStretchMode = SetStretchBltMode(hDC:=BufferDC, nStretchMode:=HALFTONE)
    OrigAdjust.caSize = Len(OrigAdjust)
    GetColorAdjustment hDC:=BufferDC, lpCA:=OrigAdjust

    'Define the transformation matrices
    SetWorldTransform hDC:=BufferDC, lpXform:=XFormMatrix

    'load picSource into the Buffer and apply scaling factor
    'hSrcDC:=srcHDC
    StretchBlt hDC:=BufferDC, _
               x:=0, _
               y:=0, _
               nWidth:=srcBmp.bmWidth * xsize, _
               nHeight:=srcBmp.bmHeight * xsize, _
               hSrcDC:=srcHDC, _
               xSrc:=0, _
               ySrc:=0, _
               nSrcWidth:=srcBmp.bmWidth, _
               nSrcHeight:=srcBmp.bmHeight, _
               dwRop:=vbSrcCopy

    'revert the transform settings, these can conflict with the colour adjustment
    SetWorldTransform hDC:=BufferDC, lpXform:=OldMatrix
    SetGraphicsMode hDC:=BufferDC, iMode:=OldGraphicsMode

   ' Apply the colour adustment to the Buffer DC
    SetColorAdjustment hDC:=BufferDC, lpCA:=NewAdjust

    'now apply a second call to StretchBlt, this time painting the buffer with itself!
    'hSrcDC:=BufferDC!
    StretchBlt hDC:=BufferDC, _
               X:=0, _
               Y:=0, _
               nWidth:=UserControl.ScaleWidth, _
               nHeight:=UserControl.ScaleHeight, _
               hSrcDC:=BufferDC, _
               xSrc:=0, _
               ySrc:=0, _
               nSrcWidth:=UserControl.ScaleWidth, _
               nSrcHeight:=UserControl.ScaleHeight, _
               dwRop:=vbSrcCopy

    'now revert the colour adjustment settings
    SetStretchBltMode hDC:=BufferDC, nStretchMode:=OldStretchMode
    SetColorAdjustment hDC:=BufferDC, lpCA:=OrigAdjust

    'Paint the UserControl surface with the Buffer
    BitBlt hDestDC:=UserControl.hDC, _
           X:=0, _
           Y:=0, _
           nWidth:=UserControl.ScaleWidth, _
           nHeight:=UserControl.ScaleHeight, _
           hSrcDC:=BufferDC, _
           xSrc:=0, _
           ySrc:=0, _
           dwRop:=vbSrcCopy

    'Delete objects!
    DeleteDC BufferDC
    DeleteObject BgBuffer
    UserControl.Refresh
End Sub