• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

GDIplus - resizing fails

Started by Edwin Knoppert, October 20, 2011, 10:02:02 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Edwin Knoppert

I have some code and it reduces an image from:

DPI: 305,  305
Size: 4274,  5304

to:
DPI: 305,  305
SIZE: 1009,  1252

But fails to paint.

I tried your code and the code work with your image but still not with the image i have:

http://www.jose.it-berater.org/smfforum/index.php?topic=1799.0

There is a new image handle and shows the new height and width but fails to paint.
When i use your code i reset the target size to 1000x1000 (from 100) and it shows a portion of the image, it seems to fail on the resize and shows the contents cropped.

Any idea?
(I am looking for DPI reducing actually, the new file remains 300 DPI but i can live with that)

Edwin Knoppert

I am looking for a PB version of this:
http://www.codeguru.com/forum/showthread.php?t=289821
(or this http://stackoverflow.com/questions/6072814/reduce-image-size-but-keep-maximum-quality-resolution )

Unf i can't find the correct drawimage entry which allows to draw to the new image.
I used this
        pGraphics = VD_GDIPlus_Graphics_CreateFromHDC( hDC )   
        CDW = GetProcAddress( hLib, "GdipCreateBitmapFromGraphics" )
        Call Dword CDW Using GdipCreateBitmapFromGraphics( nWidth, nHeight, pGraphics, lpImage2 )

        CDW = GetProcAddress( hLib, "GdipDrawImageRectI" )
        Call Dword CDW Using GdipDrawImageRectI( pGraphics, lpImage, 0, 0, nWidth, nHeight )

But now i see the image drawn on my screen.
I need to resize that's all :)
Using the thumbnails function generates a poor image.

Frank Brübach

#2
Hi edwin, concerning your first post I have made a short test with Cloning the Image.

My source image has size of 400x300x24 BPP.

I can only clone the image until this size limit. If I am using bigger size the scene is empty.

Quote...But fails to paint...

I can confirm your observation: here are my results after some testings:


SUB GDIP_Clone (BYVAL hdc AS DWORD)

   LOCAL hStatus AS LONG
   LOCAL pGraphics AS DWORD
   LOCAL pBitmap AS DWORD
   LOCAL pClone AS DWORD
   LOCAL strFileName AS STRING

   hStatus = GdipCreateFromHDC(hdc, pGraphics)

   '  // Create a Bitmap object from a JPEG file.
   strFileName = UCODE$("po2.jpg")
   hStatus = GdipCreateBitmapFromFile(STRPTR(strFileName), pBitmap)

   ' // Clone a portion of the bitmap
'   hStatus = GdipCloneBitmapAreaI(0, 0, 100, 100, %PixelFormatDontCare, pBitmap, pClone) 'ok :)
'   hStatus = GdipCloneBitmapAreaI(10, 10, 200, 200, %PixelFormatDontCare, pBitmap, pClone) 'ok :)
'   hStatus = GdipCloneBitmapAreaI(10, 10, 300, 200, %PixelFormatDontCare, pBitmap, pClone) ' ok :)
'   hStatus = GdipCloneBitmapAreaI(10, 10, 300, 290, %PixelFormatDontCare, pBitmap, pClone) ' ok :)
'   hStatus = GdipCloneBitmapAreaI(10, 10, 390, 290, %PixelFormatDontCare, pBitmap, pClone) ' ok :) '400x300 image-size
   'hStatus = GdipCloneBitmapAreaI(0, 0, 399, 299, %PixelFormatDontCare, pBitmap, pClone) ' ok :) '400x300 image-size
   hStatus = GdipCloneBitmapAreaI(0, 0, 400, 300, %PixelFormatDontCare, pBitmap, pClone) ' ok :) '400x300 image-size

'    hStatus = GdipCloneBitmapAreaI(0, 0, 401, 301, %PixelFormatDontCare, pBitmap, pClone) ' not ok :) '400x300 image-size
'   hStatus = GdipCloneBitmapAreaI(10, 10, 410, 310, %PixelFormatDontCare, pBitmap, pClone) ' not ok :) '400x300 image-size

   ' // Draw the clone
   hStatus = GdipDrawImageI(pGraphics, pClone, 0, 0)

   ' // Cleanup
   IF pClone THEN GdipDisposeImage(pClone)
   IF pBitmap THEN GdipDisposeImage(pBitmap)
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)

END SUB


I don't know why you are using "GdipCloneBitmapAreaI" function, but perhaps there is another alternative for you. My suggestion is that you only can clone bitmap pixel of relation 1:1 for realisation. I have not explored more about this topic but I was curious if cloning are working in such case.

best regards, frank

Edwin Knoppert

I think i have used the wrong function myself and will always crop but not resize.
Goal is to resize my 7MB file (4274,  5304) to something compressed (png) below the 1MB threshold set.
I have succesfully use the .NET code here:
http://stackoverflow.com/questions/6072814/reduce-image-size-but-keep-maximum-quality-resolution

But i can't find the correct API's to do a similar thing.
All graphic calls need some extra setting.
Important is to maintain alphablending so standard HBITMAP behaviour is not what i look for.



Patrice Terrier

Yes, you are using the wrong API.

If what you want is just to stretch/resize the image, then use GdipDrawImageRectRectI

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Edwin Knoppert

OK, but i need a copy of the image

Patrice Terrier

Then create a bitmap/image of the good size, and use it as the graphics target for GdipDrawImageRectRectI.

GdipDrawImageRectRectI(graphics, ImageHandle, xDest, yDest, wDest, hDest, xSrce, ySrce, wSrce, hSrce, 2,  0)

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Edwin Knoppert

That's what i already did but did not work for some reason.
What i did:
1) Load the big image
2) Made a clone with the smaller size
3) Obtained the graphics from that clone (...context())
4) Drew the big image onto the cloned graphics handle

Maybe i need to create a new graphics object with the new dimensions (but how, seems CreateDC() gdi remains the only option)

Frank Brübach

the advice from patrice isn't so bad I am thinking. edwin, give it a try ;)

I've made a short test for it. beside that you can add a lot of images there (like thumbnails) if you're using for example several "hStatus... hStatus1, hStatus2.." for drawing new images and you need only one time to call "GDIP_GdipDrawImageRectRect" function in %WM_Paint part. if you want to manipulate the images you can do like this way..

'-----> do manipulations here if you like ------------------------------------------------>
   'you can resize the image or oversize it whatever you want to do...
   
   ' // Define the portion of the image to draw.
   srcX = 120 '60.0! '70.0!
   srcY = 110  '50.0! '20.0!
   srcwidth = 100.0!
   srcheight = 100.0!
'-----> do manipulations here if you like ------------------------------------------------>


example part:
SUB GDIP_GdipDrawImageRectRect (BYVAL hdc AS DWORD)

   LOCAL hStatus AS LONG
   LOCAL pGraphics AS DWORD
   LOCAL pImage AS DWORD
   LOCAL strFileName AS STRING
   LOCAL nWidth AS DWORD
   LOCAL nHeight AS DWORD
   LOCAL srcx AS SINGLE
   LOCAL srcy AS SINGLE
   LOCAL srcwidth AS SINGLE
   LOCAL srcheight AS SINGLE
   LOCAL pRemapAttributes AS DWORD
   LOCAL redToBlue AS GDIP_COLORMAP
   DIM   destPoints(2) AS POINTF

   hStatus = GdipCreateFromHDC(hdc, pGraphics)

   ' // Create the Image object
   strFileName = UCODE$("po2.jpg")
   hStatus = GdipLoadImageFromFile(STRPTR(strFileName), pImage)

   ' // Draw the original source image.
   hStatus = GdipDrawImage(pGraphics, pImage, 10, 10)

'-----> do manipulations here if you like ------------------------------------------------>
   'you can resize/resample the image to whatever size you want to do...
   
   ' // Define the portion of the image to draw.
   srcX = 120'60.0! '70.0!
   srcY = 110 '50.0! '20.0!
   srcwidth = 100.0!
   srcheight = 100.0!
'----------------------------------------------------->

   ' // Get the width and height of the image.
   hStatus = GdipGetImageWidth(pImage, nWidth)
   hStatus = GdipGetImageHeight(pImage, nHeight)

   ' // Create an ImageAttributes object that specifies a recoloring from red to blue.
   hStatus = GdipCreateImageAttributes(pRemapAttributes)
   redToBlue.oldColor = GDIP_ARGB(255, 255, 0, 0)
   redToBlue.newColor = GDIP_ARGB(255, 0, 0, 255)
   hStatus = GdipSetImageAttributesRemapTable(pRemapAttributes, %ColorAdjustTypeDefault, %TRUE, 1, redToBlue)

   ' Draw the cropped image                           '200,10
   hStatus = GdipDrawImageRectRect(pGraphics, pImage, 550, 290, nWidth, nHeight, srcx, srcy, _
             srcwidth, srcheight, %UnitPixel, pRemapAttributes, %NULL, %NULL)

   ' // Cleanup
   IF pRemapAttributes THEN GdipDisposeImageAttributes(pRemapAttributes)
   IF pImage THEN GdipDisposeImage(pImage)
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)

END SUB


best regards, frank

Edwin Knoppert

This resize thing cost me several days now, they won't be so pleased with me on monday :)
I need to make a (smaller) file copy, and not paint it as a smaller image.

I may be close but i am lost on the cloning and drawing part.
Hopefully i get me some more help on this, i need a file-in / smaller file-out functionality.
I already use gdiplus for brightness and such so it would be odd to use a different mechanism.

Any suggestions?
I am about to implement the perfectly working .NET functionality but that would be giving in right?

Patrice Terrier

QuoteThis resize thing cost me several days now,

I know of a DeLuxe solution {as would say Theo}, but you probably prefer to write everything from ground zero, then extra days of work is the price you have to pay to have your own.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Edwin Knoppert

I think i made it to difficult for myself.
I was afraid i would loose the alphablending when i paint to a new DC.
Monday i'll create a compatible dc and draw the original to the new one, hopefully the image remains ok this way.
There are solutions enough but goal was using the gdiplus api's and keep the image intact regarding alphablending.

Edwin Knoppert

I failed again but i resorted to my 2nd option, draw to DC and use that for saving, this may possibly loose the alphablending:

(PwrDev code but you'll get the idea)


Sub GDIP_Clone (ByVal hdc As Dword)

    Local hStatus   As Long
    Local pGraphics As Dword
    Local pImage    As Dword
    Local hBitmap   As Dword
    Local pData     As Long
    Local hOldDIB   As Long
    Local hMemDC    As Long
    Local hDIB      As Long
    Local BMI       As BITMAPINFO
    Local CDW       As Dword
    Local T         As String
    Local pStream   As Dword Ptr

    pImage = VD_GDIPlus_LoadFromFile( "D:\Nieuwe map (3)\346074.jpg" )
    If pImage = 0 Then Exit Sub
   
    BMI.bmiHeader.biSize        = SizeOf( BMI.bmiHeader )
    BMI.bmiHeader.biWidth       = 614
    BMI.bmiHeader.biHeight      = 762
    BMI.bmiHeader.biPlanes      = 1
    BMI.bmiHeader.biBitCount    = 24
    BMI.bmiHeader.biCompression = %BI_RGB

    hMemDC = CreateCompatibleDC( hDC )
    hDIB = CreateDIBSection( hDC, BMI, %DIB_RGB_COLORS, pData, 0, 0 )
    hOldDIB = SelectObject( hMemDC, hDIB )

    pGraphics = VD_GDIPlus_Graphics_CreateFromHDC( hMemDC )
   
    CDW = GetProcAddress( VD_GDIPlus_Props.hLib, "GdipDrawImageRectRectI" )
    Call Dword CDW Using VD__GdipDrawImageRectRectI( pGraphics, pImage, 0, 0, 614, 762, 0, 0, 4274, 5304, 2, 0, 0, 0 )
    SelectObject( hMemDC, hOldDIB )
   
    hBitmap = VD_GDIPlus_CreateBitmapFromHBITMAP( hDIB, 0 )

    pStream = VD_GDIPlus_SaveImageToStream( hBitmap, "image/png" )
    If pStream > 0 Then           
        T = VD_IStream_ReadAllStr( pStream )
        VD_SaveToFile( "d:\testimg.png", T )
        Call Dword @@pStream[2] Using VD_GDIPlus_CallCom( pStream )       
    End If

    VD_GDIPlus_Graphics_Delete( pGraphics ): pGraphics = 0
    DeleteObject( hDIB ): hDIB = 0
    DeleteDC( hMemDC ): hMemDC = 0
   
    VD_Debug_Print "FileSize " & Str$( Len( T ) )
 

End Sub


Edwin Knoppert

I was so much unlucky on this part the last week and even today, i can only laugh (but cry) :)

Anyway, here is a tip, i found out the hard way (and after a lot of extra nonsense code) that gdiplus doesn't like threads.
I had this image handle and drew it on a memory dc but that part runs in a thread, it drew that part but then it won't draw in the main thread again.
This means i can not use the paint engine from gdiplus for this matter which i hoped for, i have to rewrite my code to ordinary bitblt stuff.