Redimensionner une image PNG

Programmation d'applications complexes
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Redimensionner une image PNG

Message par Le Soldat Inconnu »

Coucou,

une bonne colle.
Et je pense que Denis a la solution, il en avait parlé mais je ne retrouve pas le sujet en question.

Donc j'ai une image PNG avec couche alpha

Cette image est pour un skin

J'ai donc besoin de la découper en X partie, les bordures et les zones redimensionnable.

Pour découper, GrabImage fonctionne

Mais pour redim, rien

voici un petit code de test
il faut une image PNG nommée "test.png"

Code : Tout sélectionner

UsePNGImageDecoder()

LoadImage(1, "test.png")

If OpenWindow(0, 0, 0, 300, 300, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0
  End
EndIf

GrabImage(1, 2, 0, 0, 64, 64)
CopyImage(1, 3)
ResizeImage(3, 64, 64)

CreateImage(0, 300, 300)
StartDrawing(ImageOutput(0))
  Box(0, 0, 300, 300, GetSysColor_(#COLOR_3DFACE))
  DrawAlphaImage(ImageID(1), 0, 0)
  DrawAlphaImage(ImageID(2), 150, 0)
  DrawAlphaImage(ImageID(3), 0, 150)
StopDrawing()

ImageGadget(0, 0, 0, 300, 300, ImageID(0))

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Menu
      Select EventMenu() ; Menus
          
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget() ; Gadgets
          
      EndSelect
  EndSelect
  
Until Event = #PB_Event_CloseWindow
Merci
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Rectification, cela ne marche pas que dans le mode SMOOTH
en RAW, c'est bon.

voir ce code
il faut toujours une image "test.png"

Code : Tout sélectionner

UsePNGImageDecoder()

LoadImage(1, "test.png")

If OpenWindow(0, 0, 0, 300, 300, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0
  End
EndIf

GrabImage(1, 2, 0, 0, 64, 64)
CopyImage(1, 3)
ResizeImage(3, 256, 256, #PB_Image_Raw)

CreateImage(0, 300, 300)
StartDrawing(ImageOutput(0))
  Box(0, 0, 300, 300, GetSysColor_(#COLOR_3DFACE))
  DrawAlphaImage(ImageID(1), 0, 0)
  DrawAlphaImage(ImageID(2), 150, 0)
  DrawAlphaImage(ImageID(3), 0, 150)
StopDrawing()

ImageGadget(0, 0, 0, 300, 300, ImageID(0))

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Menu
      Select EventMenu() ; Menus
          
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget() ; Gadgets
          
      EndSelect
  EndSelect
  
Until Event = #PB_Event_CloseWindow
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

bon, j'ai codé un palliatif en attendant que Fred intégre la couche alpha dans ResizeImage

voilà la bête, il faut toujours un png nommé test mis avec le code.
par exemple cette image :
Image

Code : Tout sélectionner

UsePNGImageDecoder()

Procedure ResizeAlphaImage(Image, Width, Height)
  Protected bmi.BITMAPINFO, hdc.l, Memoire, n, nn, bm.BITMAP, Fin, Position, Resultat, ImageAlpha, Memoire2, Memoire3
  
  GetObject_(ImageID(Image), SizeOf(BITMAP), @bm.BITMAP)
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
  
  Memoire = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Memoire
    
    hdc = CreateCompatibleDC_(GetDC_(ImageID(Image)))
    If hdc
      GetDIBits_(hdc, ImageID(Image), 0, bm\bmHeight, Memoire, @bmi, #DIB_RGB_COLORS) ; on récupère la zone mémoire de l'image
      DeleteDC_(hdc)
      
      ; On convertit la couche Alpha en couleur grise
      Fin = Memoire + bm\bmWidth * bm\bmHeight * 4 - 4
      For Position = Memoire To Fin Step 4
        PokeL(Position, PeekB(Position + 3))
      Next
      
      ImageAlpha = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight, 32)
      If ImageAlpha
        hdc = CreateCompatibleDC_(GetDC_(ImageID(ImageAlpha)))
        If hdc
          SetDIBits_(hdc, ImageID(ImageAlpha), 0, bm\bmHeight, Memoire, @bmi, #DIB_RGB_COLORS) ; on envoie la couche alpha dans la nouvelle image
          DeleteDC_(hdc)
          
          ; On redimensionne les images
          ResizeImage(Image, Width, Height)
          ResizeImage(ImageAlpha, Width, Height)
          
          GetObject_(ImageID(Image), SizeOf(BITMAP), @bm.BITMAP)
          bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
          bmi\bmiHeader\biWidth = bm\bmWidth
          bmi\bmiHeader\biHeight = bm\bmHeight
          bmi\bmiHeader\biPlanes = 1
          bmi\bmiHeader\biBitCount = 32
          bmi\bmiHeader\biCompression = #BI_RGB
          
          Memoire2 = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
          If Memoire2
            Memoire3 = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
            If Memoire3
              hdc = CreateCompatibleDC_(GetDC_(ImageID(ImageAlpha)))
              If hdc
                GetDIBits_(hdc, ImageID(ImageAlpha), 0, bm\bmHeight, Memoire2, @bmi, #DIB_RGB_COLORS) ; on récupère la zone mémoire de l'image
                DeleteDC_(hdc)
                hdc = CreateCompatibleDC_(GetDC_(ImageID(Image)))
                If hdc
                  GetDIBits_(hdc, ImageID(Image), 0, bm\bmHeight, Memoire3, @bmi, #DIB_RGB_COLORS) ; on récupère la zone mémoire de l'image
                  ; On recrée la couche alpha de l'image finale
                  Fin = bm\bmWidth * bm\bmHeight * 4 - 4
                  For Position = 0 To Fin Step 4
                    PokeB(Memoire3 + Position + 3, PeekB(Memoire2 + Position))
                  Next
                  SetDIBits_(hdc, ImageID(Image), 0, bm\bmHeight, Memoire3, @bmi, #DIB_RGB_COLORS) ; on envoie la couche alpha dans la nouvelle image
                  DeleteDC_(hdc)
                  Resultat = ImageAlpha
                EndIf
              EndIf
              FreeMemory(Memoire3)
            EndIf
            FreeMemory(Memoire2)
          EndIf
        EndIf
        FreeImage(ImageAlpha)
      EndIf
    EndIf
    FreeMemory(Memoire)
  EndIf
  ProcedureReturn Resultat
EndProcedure

LoadImage(1, "test.png")

If OpenWindow(0, 0, 0, 300, 300, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0
  End
EndIf

x = ImageWidth(1) / 2
y = ImageHeight(1) / 2

Temps1 = ElapsedMilliseconds()
For n = 0 To 100
  CopyImage(1, 3)
  ResizeImage(3, x, y, #PB_Image_Raw)
Next
Temps2 = ElapsedMilliseconds()
For n = 0 To 100
  CopyImage(1, 4)
  ResizeAlphaImage(4, x, y)
Next
Temps3 = ElapsedMilliseconds()

MessageRequester("Temps", "Normal = " + Str(Temps2 - Temps1) + Chr(10) + "Alpha = " + Str(Temps3 - Temps2))

CreateImage(0, 300, 300)
StartDrawing(ImageOutput(0))
  Box(0, 0, 300, 300, GetSysColor_(#COLOR_3DFACE))
  DrawAlphaImage(ImageID(1), 0, 0)
  DrawAlphaImage(ImageID(3), 0, 150)
  DrawAlphaImage(ImageID(4), 150, 150)
StopDrawing()

ImageGadget(0, 0, 0, 300, 300, ImageID(0))

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Menu
      Select EventMenu() ; Menus
          
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget() ; Gadgets
          
      EndSelect
  EndSelect
  
Until Event = #PB_Event_CloseWindow

comment ça fonctionne ?
c'est pas la bonne question, j'ai fait au plus simple et donc pas très rapide

en gros, je récupère la couche alpha que je transforme en image en nuance de gris

je redim l'image de base et l'image représentant la couche alpha

puis je recombine les 2 images.


il serait tellement plus simple de reprendre l'algo qui gère les couche R, G ou B et de l'appliquer à l'alpha mais bon, l'ami Fred n'a pas répondu à ma demande.
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Cool, je garde...
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

j'ai trouvé sur le fofo des anglais, ça utilise la lib GDI

Code : Tout sélectionner

; netmaestro's gdiplus thumbnail creator
;
;----------------------------------------------------------------------------
;                     GDIPlus Initialization Section
;----------------------------------------------------------------------------
;
CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0
  Structure GdiplusStartupInput
    GdiPlusVersion.l
    *DebugCallback
    SuppressBackgroundThread.l
    SuppressExternalCodecs.l
  EndStructure
CompilerEndIf 

Global PixelFormatIndexed        = $00010000 ; Indexes into a palette
Global PixelFormatGDI            = $00020000 ; Is a GDI-supported format
Global PixelFormatAlpha          = $00040000 ; Has an alpha component
Global PixelFormatPAlpha         = $00080000 ; Pre-multiplied alpha
Global PixelFormatExtended       = $00100000 ; Extended color 16 bits/channel
Global PixelFormatCanonical      = $00200000
Global PixelFormatUndefined      = 0
Global PixelFormatDontCare       = 0
Global PixelFormat1bppIndexed    = (1 | ( 1 << 8) |PixelFormatIndexed |PixelFormatGDI)
Global PixelFormat4bppIndexed    = (2 | ( 4 << 8) |PixelFormatIndexed |PixelFormatGDI)
Global PixelFormat8bppIndexed    = (3 | ( 8 << 8) |PixelFormatIndexed |PixelFormatGDI)
Global PixelFormat16bppGrayScale = (4 | (16 << 8) |PixelFormatExtended) ; $100
Global PixelFormat16bppRGB555    = (5 | (16 << 8) |PixelFormatGDI)
Global PixelFormat16bppRGB565    = (6 | (16 << 8) |PixelFormatGDI)
Global PixelFormat16bppARGB1555  = (7 | (16 << 8) |PixelFormatAlpha |PixelFormatGDI)
Global PixelFormat24bppRGB       = (8 | (24 << 8) |PixelFormatGDI)
Global PixelFormat32bppRGB       = (9 | (32 << 8) |PixelFormatGDI)
Global PixelFormat32bppARGB      = (10 | (32 << 8) |PixelFormatAlpha |PixelFormatGDI |PixelFormatCanonical)
Global PixelFormat32bppPARGB     = (11 | (32 << 8) |PixelFormatAlpha |PixelFormatPAlpha |PixelFormatGDI)
Global PixelFormat48bppRGB       = (12 | (48 << 8) |PixelFormatExtended)
Global PixelFormat64bppARGB      = (13 | (64 << 8) |PixelFormatAlpha  |PixelFormatCanonical |PixelFormatExtended)
Global PixelFormat64bppPARGB     = (14 | (64 << 8) |PixelFormatAlpha  |PixelFormatPAlpha |PixelFormatExtended)
Global PixelFormatMax            =  15 

Prototype GdiplusStartup( *token, *input, mode )
Prototype GdipCreateBitmapFromFile( Filename, *image )
Prototype GdipGetImageWidth( *image, *Width )
Prototype GdipGetImageHeight( *image, *Height )
Prototype GdipGetImagePixelFormat( *image, *Format )
Prototype GdipCreateFromHDC( hdc, *gfx)
Prototype GdipDrawImageRectI( *gfx, *image, x, y, Width, Height )
Prototype GdipDeleteGraphics( *gfx )
Prototype GdipDisposeImage( *image )
Prototype GdiplusShutdown( *token )

OpenLibrary(0, "gdiplus.dll")

Global Startup.GdiplusStartup                        = GetFunction( 0, "GdiplusStartup" )         
Global CreateBitmapFromFile.GdipCreateBitmapFromFile = GetFunction( 0, "GdipCreateBitmapFromFile" )
Global GetImageWidth.GdipGetImageWidth               = GetFunction( 0, "GdipGetImageWidth" )               
Global GetImageHeight.GdipGetImageHeight             = GetFunction( 0, "GdipGetImageHeight" )     
Global GetImagePixelFormat.GdipGetImagePixelFormat   = GetFunction( 0, "GdipGetImagePixelFormat" )
Global CreateFromHDC.GdipCreateFromHDC               = GetFunction( 0, "GdipCreateFromHDC" )     
Global DrawImageRectI.GdipDrawImageRectI             = GetFunction( 0, "GdipDrawImageRectI" )     
Global DeleteGraphics.GdipDeleteGraphics             = GetFunction( 0, "GdipDeleteGraphics" )     
Global DisposeImage.GdipDisposeImage                 = GetFunction( 0, "GdipDisposeImage" )       
Global Shutdown.GdiplusShutdown                      = GetFunction( 0, "GdiplusShutdown" ) 
;     
;-----------------------------------------------------------------------------
;                      End GDIPlus Initialization Section
;-----------------------------------------------------------------------------

Procedure StringToBStr (string$) ; By Zapman Inspired by Fr34k
  Protected Unicode$ = Space(Len(string$)* 2 + 2)
  Protected bstr_string.l
  PokeS(@Unicode$, string$, -1, #PB_Unicode)
  bstr_string = SysAllocString_(@Unicode$)
  ProcedureReturn bstr_string
EndProcedure

ProcedureDLL LoadThumbnail(ImageNumber, xsize, ysize, Filename.s)
  input.GdiplusStartupInput
  input\GdiPlusVersion = 1
  Startup( @*token, @input, #NULL)
  
  CreateBitmapFromFile( StringToBStr(Filename), @*image)
  
  GetImageWidth( *image, @Width.l )
  GetImageHeight( *image, @Height.l )
  GetImagePixelFormat( *image, @Format.l )
  
  Select Format
    Case PixelFormat1bppIndexed: bits_per_pixel = 1
    Case PixelFormat4bppIndexed: bits_per_pixel = 4
    Case PixelFormat8bppIndexed: bits_per_pixel = 8
    Case PixelFormat16bppARGB1555: bits_per_pixel = 16
    Case PixelFormat16bppGrayScale: bits_per_pixel = 16
    Case PixelFormat16bppRGB555: bits_per_pixel = 16
    Case PixelFormat16bppRGB565: bits_per_pixel = 16
    Case PixelFormat24bppRGB: bits_per_pixel = 24
    Case PixelFormat32bppARGB: bits_per_pixel = 32
    Case PixelFormat32bppPARGB: bits_per_pixel = 32
    Case PixelFormat32bppRGB: bits_per_pixel = 32
    Case PixelFormat48bppRGB: bits_per_pixel = 48
    Case PixelFormat64bppARGB: bits_per_pixel = 64
    Case PixelFormat64bppPARGB: bits_per_pixel = 64
    Default : bits_per_pixel = 32
  EndSelect
  
  Retval = CreateImage(ImageNumber, xsize, ysize, bits_per_pixel)
  hdc = StartDrawing(ImageOutput(ImageNumber))
    CreateFromHDC( hdc, @*gfx )
    DrawImageRectI( *gfx, *image, 0, 0, xsize, ysize )
  StopDrawing() 
  DeleteGraphics( *gfx ) 
  
  DisposeImage( *image )
  Shutdown( *token )
  
  ProcedureReturn Retval
EndProcedure

tt = ElapsedMilliseconds()
For i = 1 To 50
  LoadThumbnail(0, 64, 64, "ResizeAlphaImage.png") ; input image can be any size; parameters are for thumbnail-out size
Next
MessageRequester("Time to create 50 Thumbnails:",Str((ElapsedMilliseconds()-tt) / 50)+" ms")

CreateImage(1, 64, 64, 32)
StartDrawing(ImageOutput(1))
  Box(0, 0, 64, 64, GetSysColor_(#COLOR_3DFACE))
  DrawAlphaImage(ImageID(0), 0, 0)
StopDrawing()

CloseLibrary(0)

OpenWindow(0,0,0,382,202,"",$CF0001)
CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,0,0,ImageID(1))
Repeat:Until WaitWindowEvent() = #WM_CLOSE
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre