Применение к GDI DeviceContext регулировки вращения и цвета приводит к сбросу цветов - PullRequest
0 голосов
/ 02 сентября 2011

Я использую вызовы API для преобразования объекта Bitmap.У меня есть различные физические преобразования (вращение, отражение, масштабирование, смещение), а также некоторые настройки цвета (инверсия, яркость и контрастность)

Все работает отлично, за исключением случаев, когда я использую преобразования вращения или сдвига в сочетании срегулировка цвета.В этом случае цвета возвращаются к исходному изображению.

Интересно, что эта проблема зависит от недиагональных факторов (eM12 и eM21 ниже) в матрице XForm.Например, вот матрица вращения:

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 голосов
/ 02 сентября 2011

ОК, я нашел решение. Я разделил физические преобразования и настройки цвета на два отдельных вызова StretchBlt. В перерыве я сбрасываю матрицу 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
...