Jump to content

GDIPLUS and GdipSetInterpolationMode


ChrisL
 Share

Recommended Posts

I have some code where I'm trying to print photo's to a printer.

I'm trying to resize them using GdipSetInterpolationMode but whatever settings I use the image is still showing lots of compression looking artifacts and jagged angles and curves, the original image is a 10mp file so its fairly large and is generally being scaled down.

I've set the printer to Adobe PDF while I'm testing but it would normally be a proper printer.

You also need PrintWinAPI.au3 from the forums if you really want to print.

One other thing is and I don't really understand this either. When I draw the new image on to the printer hgraphic I have to divide pageWidth and pageHeight by 3 (the printer is 300dpi) I would have expected to just draw to the dimensions supplied by pageWidth and pageHeight.

Any ideas?

Thanks

Chris

#include <GDIPlus.au3>
#include <WinAPI.au3>
#Include <PrintWinAPI.au3>

Global enum _
    $RotateNoneFlipNone = 0 , _
    $Rotate90FlipNone = 1 , _
    $Rotate180FlipNone = 2 , _
    $Rotate270FlipNone = 3 , _
    $RotateNoneFlipX = 4 , _
    $Rotate90FlipX = 5 , _
    $Rotate180FlipX = 6 , _
    $Rotate270FlipX = 7 , _
    $RotateNoneFlipY = 6 , _
    $Rotate90FlipY = 7 , _
    $Rotate180FlipY = 4 , _
    $Rotate270FlipY = 5 , _
    $RotateNoneFlipXY = 6 , _
    $Rotate90FlipXY = 7 , _
    $Rotate180FlipXY = 0 , _
    $Rotate270FlipXY = 1

Global enum _
    $InterpolationModeInvalid  =  -1, _
    $InterpolationModeDefault  =  0, _
    $InterpolationModeLowQuality  =  1, _
    $InterpolationModeHighQuality =  2, _
    $InterpolationModeBilinear  =  3, _
    $InterpolationModeBicubic  =  4, _
    $InterpolationModeNearestNeighbor = 5, _
    $InterpolationModeHighQualityBilinear = 6, _
    $InterpolationModeHighQualityBicubic = 7
;Local $a6x8[2]=[1800,2400]

$Image  = @DesktopDir & "\DSCF0363.JPG"
$Printer = "Adobe PDF"

$ret = _PrintImage($Printer,$Image,"test")
If @error then Msgbox(0,"",@error & " " & @extended & " " & $ret)


Func _PrintImage($s_PrinterName,$ImagePath,$s_DocName="")

    If Not FileExists($ImagePath) then Return "Error File Does not exist"

    ;$aSizeArray = Eval( $aSizeArray )
    $hPrintDc = _WinAPI_CreateDC("winspool", $s_PrinterName)
    If $hPrintDc = 0 then Return "Error Printer Not Found" ;No printer found

    $PageWidth = _WinAPI_GetDeviceCaps($hPrintDC, $HORZRES) ; Get print page width
    $PageHeight = _WinAPI_GetDeviceCaps($hPrintDC, $VERTRES) ; Get print page height

    ConsoleWrite($PageWidth & " x " & $PageHeight & @crlf)


    $DocName = DllStructCreate("char DocName[" & StringLen($s_DocName & chr(0)) & "]")
    DllStructSetData($DocName, "DocName", $s_DocName & chr(0)); Size of DOCINFO structure
    $DOCINFO = DllStructCreate($tagDOCINFO); Structure for Print Document info
    DllStructSetData($DOCINFO, "Size", 20); Size of DOCINFO structure
    DllStructSetData($DOCINFO, "DocName", DllStructGetPtr($DocName)); Set name of print job (Optional)

    ; start new print doc
    $result = _WinAPI_StartDoc($hPrintDc, $DOCINFO)
    ; start new page
    $result = _WinAPI_StartPage($hPrintDc)

    _GDIPlus_Startup ()

    $hGraphic = _GDIPlus_GraphicsCreateFromHDC ($hPrintDc)

    $hImage = _GDIPlus_ImageLoadFromFile($ImagePath)

    $iW = _GDIPlus_ImageGetWidth($hImage)
    $iH = _GDIPlus_ImageGetHeight($hImage)

    $ret = _GDIPLUS_GraphicsSetInterpolationMode($hGraphic,$InterpolationModeHighQualityBicubic)
    ConsoleWrite("Interpolation mode " & $InterpolationModeHighQualityBicubic & " " & $Ret & @crlf)

    If ($PageHeight > $PageWidth) and  ($iW > $iH) then ; Need to rotate the image
        _GDIPlus_ImageRotateFlip($hImage,$Rotate90FlipNone)
        ;Switch W & H Values
        Local $tmp
        $tmp = $iH
        $iH = $iW
        $iW = $tmp
    EndIf

    $aRect = _GetImageSectionScaleToFill($iW,$iH,$PageWidth,$PageHeight)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage, $aRect[0], $aRect[1],$aRect[2],$aRect[3],0,0,$PageWidth/3,$PageHeight/3)


    _GDIPlus_ImageDispose ($hImage)
    _GDIPlus_GraphicsDispose ($hGraphic)
    _GDIPlus_Shutdown ()

    ; End the page
    $result = _WinAPI_EndPage($hPrintDc)
    ; End the print job
    $result = _WinAPI_EndDoc($hPrintDc)
    ; Delete the printer device context
    _WinAPI_DeleteDC($hPrintDc)

    Return "Done"
EndFunc


Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iInterMode = 0)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "long", $hGraphics, "long", $iInterMode)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aRet[0], 0, $aRet[0] = 0)
EndFunc ;==>_GDIPLUS_GraphicsSetInterpolationMode


Func _GetImageSectionScaleToFill($inWidth,$inHeight,$outWidth,$outHeight)
     Local $Ret[4]

    If $outWidth > $outHeight then ;landscape

        $OutAspect = Round($outWidth/$outHeight,2)
        $inAspect = Round($inWidth/$inHeight,2)

        If $OutAspect >= $inAspect then ;Landscape Scale up

            ;take the original Width and devide it by the out aspect ratio to get the Height of the requied section
            ;take the inHeight away from the new Height and devide it by 2 to get the Y start point

            ;Msgbox(0,"Landscape","Resize the original by Width")
            ;OK on engine lid
            $newHeight = $inWidth / $OutAspect
            $StartPixel = ($inHeight - $newHeight) / 2

            $ret[0] = 0
            $ret[1] = $StartPixel
            $ret[2] = $inWidth
            $ret[3] = $newHeight
            ;_arrayDisplay($ret,"1 Landscape Enlarge" )

        Else ;Landscape Scale Down

            ;take the original height and times it by the out aspect ratio to get the width of the requied section
            ;take the new width away from the original width and devide it by 2 to get the X start point

            ;Msgbox(0,"Landscape","Resize the original by Height")
            $newWidth = $inHeight * $OutAspect
            $startPixel = ($inWidth - $newWidth) / 2

            $ret[0] = $startPixel
            $Ret[1] = 0
            $ret[2] = $newWidth
            $ret[3] = $inHeight
            ;_arrayDisplay($ret,"2 Landscape Shrink" )
        EndIf


    Else    ;If $outWidth <= $outHeight then ;Portrait

            $OutAspect = Round($outHeight/$outWidth,2)
            $InAspect = Round($inHeight/$inWidth,2)

        If $OutAspect > $inAspect then

            ;Msgbox(0,"Portrait Shrink","Resize the original by Height")
            $newWidth = $inHeight / $OutAspect
            $startPixel = ($inWidth - $newWidth) / 2

            $ret[0] = $startPixel
            $Ret[1] = 0
            $ret[2] = $newWidth
            $ret[3] = $inHeight

            ;_ArrayDisplay($ret,"3 Portrait Enlarge Resize by height")


        Else ;portrait

            ;Msgbox(0,"Portrait Shrink ","Resize the original by Width")
            ;OK on the wall
            $newHeight = $inWidth * $OutAspect
            $StartPixel = ($inHeight - $newHeight) / 2

            $ret[0] = 0
            $ret[1] = $StartPixel
            $ret[2] = $inWidth
            $ret[3] = $newHeight

            ;_ArrayDisplay($ret,"4 Portrait Enlarge Resize by Width")

            EndIf

    EndIf

        ;MSgbox(0,"","OutAspect =" & $OutAspect & @crlf & "inAspect = " & $inAspect)

    Return $Ret

EndFunc



; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_mageRotateFlip
; Description ...: rotates and flips an image
; Syntax.........: _GDIPlus_mageRotateFlip($hImage,$rfType)
; Parameters ....: $hImage      - Handle to an image object
;                  $rfType   ;[in] Element of the  RotateFlipType enumeration that specifies the type of
;                               rotation and the type of flip.
;
; Return values .: Success      - True
;                  Failure      - False
; ===============================================================================================================================
Func  _GDIPlus_ImageRotateFlip($hImage,$rfType)
    Local $aResult
    $aResult = DllCall($ghGDIPDll,"int","GdipImageRotateFlip","hwnd",$hImage,"long",$rfType)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc
Link to comment
Share on other sites

  • 2 months later...

Try this code for Interpolation

Your Coder don't work

$aRet = DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "long", $hGraphics, "long", $iInterMode) ; BAD

$aRet = DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iInterMode) ; OK

Global enum _
    $InterpolationModeInvalid  =  -1, _
    $InterpolationModeDefault  =  0, _
    $InterpolationModeLowQuality  =  1, _
    $InterpolationModeHighQuality =  2, _
    $InterpolationModeBilinear  =  3, _
    $InterpolationModeBicubic  =  4, _
    $InterpolationModeNearestNeighbor = 5, _
    $InterpolationModeHighQualityBilinear = 6, _
    $InterpolationModeHighQualityBicubic = 7


Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iInterMode = 0)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iInterMode)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aRet[0], 0, $aRet[0] = 0)
EndFunc ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _GDIPLUS_GraphicsGetInterpolationMode($hGraphics)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipGetInterpolationMode", "hwnd", $hGraphics, "int*", 0)
    If @error Then Return SetError(@error, @extended, False)
    ;Return $aRet
    Return SetError($aRet[0], 0, $aRet[2])
EndFunc ;==>_GDIPLUS_GraphicsGetInterpolationMode

Testing Program

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>

Global $Exit = False
If Not HotKeySet("{Esc}","FExit") Then Exit
Func FExit()
    $Exit = True
EndFunc

#region GDIPlus Extras
; Testing result Set->Get =  0->3 1->3 2->7 3->3 4->4 5->5 6->6 7->7
Global enum _
    $InterpolationModeInvalid  =  -1, _
    $InterpolationModeDefault  =  0, _
    $InterpolationModeLowQuality  =  1, _
    $InterpolationModeHighQuality =  2, _
    $InterpolationModeBilinear  =  3, _
    $InterpolationModeBicubic  =  4, _
    $InterpolationModeNearestNeighbor = 5, _
    $InterpolationModeHighQualityBilinear = 6, _
    $InterpolationModeHighQualityBicubic = 7


Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iInterMode = 0)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iInterMode)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aRet[0], 0, $aRet[0] = 0)
EndFunc ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _GDIPLUS_GraphicsGetInterpolationMode($hGraphics)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipGetInterpolationMode", "hwnd", $hGraphics, "int*", 0)
    If @error Then Return SetError(@error, @extended, False)
    ;Return $aRet
    Return SetError($aRet[0], 0, $aRet[2])
EndFunc ;==>_GDIPLUS_GraphicsGetInterpolationMode

#endregion GDIPlus Extras

$sInterpolation = StringSplit("Invalid,Default,LowQuality,HighQuality,Bilinear,Bicubic,NearestNeighbor,HighQualityBilinear,HighQualityBicubic",",",2)

Opt('MustDeclareVars', 1)

_Main()

Func _Main()
    Local $hGUI1, $hGUI2, $hImage, $hGraphic1, $hGraphic2

    ; Capture top left corner of the screen
    _ScreenCapture_Capture (@MyDocumentsDir & "\GDIPlus_Image.jpg", 0, 0, 400, 300)

    ; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", 400, 300, 0, 0)
    GUISetState()

    ; Create a GUI for the zoomed image
    $hGUI2 = GUICreate("Zoomed", 400, 300, 0, 400)
    GUISetState()

    ; Initialize GDI+ library and load image
    _GDIPlus_Startup ()
    $hImage = _GDIPlus_ImageLoadFromFile (@MyDocumentsDir & "\GDIPlus_Image.jpg")

    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND ($hGUI1)
    _GDIPlus_GraphicsDrawImage ($hGraphic1, $hImage, 0, 0)

    ; Loop until user exits
    Local $i = -1, $lt = -1, $t
    ; Draw 8x zoomed image
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND ($hGUI2)
    Do
        If TimerDiff($t) > 3000 Then
            $t = TimerInit()
            Local $RSetInter = _GDIPLUS_GraphicsSetInterpolationMode($hGraphic2, $i) ; Seta Interpolação  (0->3 1->3 2->7 3..7->3..7)
            Local $RGetInter = _GDIPLUS_GraphicsGetInterpolationMode($hGraphic2) ; Le Interpolação aceita
            WinSetTitle($hGUI2,"",StringFormat("Zoomed 8x Set(%d):%s Get(%d):%s",$i,$sInterpolation[$i+1],$RGetInter, $sInterpolation[$RGetInter+1]))
            Local $RDraw = _GDIPlus_GraphicsDrawImageRectRect ($hGraphic2, $hImage, 0, 0, 50, 50, 0, 0, 400, 300)
            $i += 1
            If $i > 7 Then $i = -1
        EndIf
    Until GUIGetMsg() = $GUI_EVENT_CLOSE Or $Exit

    ; Release resources
    _GDIPlus_GraphicsDispose ($hGraphic1)
    _GDIPlus_GraphicsDispose ($hGraphic2)
    _GDIPlus_ImageDispose ($hImage)
    _GDIPlus_Shutdown ()

    ; Clean up screen shot file
    FileDelete(@MyDocumentsDir & "\GDIPlus_Image.jpg")


EndFunc   ;==>_Main
Edited by Elias
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...