IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

[VB.NET] Copier une partie d'une image BITMAP dans une autre


Sujet :

VB.NET

  1. #1
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut [VB.NET] Copier une partie d'une image BITMAP dans une autre
    Bonjour,

    Je cherche dans le cadre d'un éditeur de niveau pour un jeu à copier une BITMAP dans une autre BITMAP à une destination précise :
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Dim b as new Bitmap("chemin_image")
    Dim allImage as new Bitmap(320, 240)
     
    ' ajoute l'image b dans allimage à la position (0,10) en pixels
    mafonction(allImage, b, 0, 10)
    Voilà reste à coder la fonction "mafonction".

    Est ce possible ? Je me suis tourné vers Graphics avec la méthode DrawImage et Clone de la classe Bitmap mais je n'arrive pas

    Une idée ? Merci

  2. #2
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Salut,
    La méthode est pourtant la bonne.
    Enfin, j'aurais plutôt tendance à utilise System.Drawing.Image plutot que System.Drawing.Bitmap mais bon.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Bitmap bmp = new Bitmap("image.bmp");
    Bitmap buffer = new Bitmap(320, 340);
     
    using (Graphics g = Graphics.FromImage(buffer))
    {
        g.DrawImage(bmp, 0, 10);
    }

    Le code est en C#, mais bon, y'a pas grandes différences.

  3. #3
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Salut,

    Oui mais ca ne fonctionne pas. Les images dans la bitmap allZone se chevauche (cf pièce jointe).
    On dirait que la position x et y de ma fonction ne fonctionne pas... (Tu peux rajouter un décalage de 50px par exemple, il va juste décaler le coin haut gauche de l'image de 50 et pas entre chaque petit "tile" de 32px par 32px...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Function test(ByVal source As Bitmap, ByVal part As Image, ByVal x As Integer, ByVal y As Integer) As Bitmap
     
            ' partB.Save("s_temp_" + x.ToString + "_" + y.ToString + ".bmp")
            Dim g As Graphics = Graphics.FromImage(source)
            g.DrawImage(part, x, y)
            g.Dispose()
     
            ' source.Save("temp_" + x.ToString + "_" + y.ToString + ".bmp")
     
            Return source
        End Function
    Et son appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Private Sub exporterZone()
            Dim allZone As New Bitmap(NBCOLONNE * TY, NBLIGNE * TX)
            For i = 0 To NBCOLONNE - 1
                For j = 0 To NBLIGNE - 1
    'récupération de la picturebox correspondante en fct de son nom                
    Dim p As PictureBox = recupererControleParNom("zone_" + i.ToString + "_" + j.ToString)
                    If Not p Is Nothing Then
                        allZone = test(allZone, p.Image, i * 32, j * 32)
                    End If
                Next
            Next
     
            allZone.Save("final.bmp")
        End Sub
    Je travaille en pixels

    Je joins aussi l'image d'origine (tile_maison.png qui est répétée dans allZone).

    Pourquoi ce décalage dans le fichier final.bmp ?


    Merci
    Images attachées Images attachées   

  4. #4
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut COPIER IMAGE DANS AUTRE IMAGE
    Bonjour,
    cela parait simple mais il surgit un probleme à propos des tailles d'image source et cible.Lorsque la taille cible est plus petite que la taille source ,la taille source sera copie mais rogne,sans compter le probleme de format et de resolution qui doivent etre identique.
    voici le bout de code et j'ai fait la copie en conservant les tailles d'origine
    des 2 images (jpeg taille identique=800x800 pixel-prise du bureau windows à savoir nenuphar.jpg et hiver.jpg).
    en copiant l'image source au centre de la cible ,elle se trouve rogne tot simplement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    Public Class Form1
        Dim copyBmp As Bitmap
        Dim cibleBmp As Bitmap
        Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     
            Try
                ' charge  image cible
                cibleBmp = New Bitmap( _
                    "C:\Documents and Settings\Bureau\WinAppCopyImage\destimg.jpg", _
                    True)
     
                Dim xCibleSize As Integer = cibleBmp.Width
                Dim yCibleSize As Integer = cibleBmp.Height
                ' affiche cible dans PictureBox1 à la taille d'origine
                PictureBox1.ClientSize = New Size(xCibleSize, yCibleSize)
                PictureBox1.Image = cibleBmp
                ' affiche taille en pixel dans Label1.
                Label1.Text = "Taille : " & cibleBmp.Width.ToString & cibleBmp.Height.ToString
                'cree un objet graphique à partir de l'image cible
                Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
     
                ' charge  image source  à copier.
                copyBmp = New Bitmap( _
                    "C:\Documents and Settings\Bureau\WinAppCopyImage\copyimg.jpg", _
                    True)
     
                'taille image à copier
                Dim xCopySize As Integer = copyBmp.Width
                Dim yCopySize As Integer = copyBmp.Height
                g.DrawImage(copyBmp, CInt(xCibleSize / 2), CInt(yCibleSize / 2), xCopySize, yCopySize)
     
     
            Catch ex As ArgumentException
                MessageBox.Show("erreur " _
                    & "verifier chemin fichier image .")
            End Try
        End Sub
     
     
     
    End Class
    bon code................

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    680
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 680
    Points : 1 183
    Points
    1 183
    Par défaut
    Bonjour,
    peut être une piste à tester.
    Ce code (largement inspiré d'un code de Balena), dessine un certain nombre d'images, en les juxtaposant et modifiant l'échelle éventuellement, sur un formulaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
        '*** rapports d'échelle horiz. et verti.
        Dim coeffEchelX As Single = 1.2
        Dim coeffEchelY As Single = 0.8
     
        Sub JuxtaposeImage(ByVal gr As Graphics, ByVal bmp As Bitmap, ByVal x As Integer, ByVal y As Integer)
            ' Start with values of parallelogram's vertex.
            Dim x0 As Integer = x
            Dim y0 As Integer = y
            Dim x1 As Integer = CInt(x + bmp.Width * coeffEchelX)
            Dim y1 As Integer = y
            Dim x2 As Integer = x
            Dim y2 As Integer = CInt(y + bmp.Height * coeffEchelY)
     
            '*** Coordonnées d'au moins 3 angles de l'image.
            Dim points() As Point = {New Point(x0, y0), New Point(x1, y1), New Point(x2, y2)}
            '*** Dessine l'image
            gr.DrawImage(bmp, points)
        End Sub
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     
            Dim gr As Graphics = Me.CreateGraphics
            Dim bmp As New Bitmap("tile_maison.png")
     
            '*** Nombres d'images à juxtaposer horiz. et verti.
            Dim nbreHoriz As Integer = 3
            Dim nbreVerti As Integer = 2
     
            For x As Integer = 1 To nbreHoriz
                For y As Integer = 1 To nbreVerti
                    JuxtaposeImage(gr, bmp, CInt(100 + (bmp.Width * coeffEchelX * x)), CInt(20 + (bmp.Height * coeffEchelY * y)))
                Next
            Next
            '' '' Create a destination rectangle 3 times as wide and twice as tall.
            ' ''Dim rect As New RectangleF(20, 120, CSng(bmp.Width / 3.5), CSng(bmp.Height / 3))
            '' '' Draw the enlarged bitmap.
            ' ''gr.DrawImage(bmp, rect)
     
            bmp.Dispose()
            gr.Dispose()
     
        End Sub

  6. #6
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Je ne suis pas sur de comprendre ton problème.

    Si j'ai bien compris tu veux extraire une petite partie de l'image "tile_maison" (cette image contient les différentes parties de "texture" qui peuvent être utilisées pour le rendu d'une maison) et coller uniquement cette partie sur la destination (allzone).
    En répétant cette partie autant qu'il le faut pour en remplir complètement l'image allzone.

    C'est ce que j'en conclut compte tenu de l'apparence de tile_maison et le fait que ta fonction dispose les éléments à 32px d'interval.
    Cependant je ne trouve pas de zone dans tile_maison qui fait 32x32 pixels.

    J'étais parti du principe que tu voulais copier l'intégralité de l'image source dans la destination. Mais ce n'est visiblement pas le cas.

    Du coup je remanie mon exemple (toujours en C#, dsl ^^') :
    Admettons que je veuille tapisser l'image destination avec la partie en bas à droite de l'image "tile_maison", ce qui ressemble à du pavé rose.

    Cette partie est un carré de 16x16 dont le coin supérieur gauche est à la position (96;80).

    Le code sera le suivant :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Image tile = Image.FromFile("tile_maison.png");
    Image dest = new Bitmap(320, 240);
     
    using (Graphics g = Graphics.FromImage(dest))
    {
        for (int i = 0; i < (320 / 16); i++)
        {
            for (int j = 0; j < (240 / 16); j++)
            {
                g.DrawImage(tile, new Rectangle(i * 16, j * 16, 16, 16), new Rectangle(96, 80, 16, 16), GraphicsUnit.Pixel);
            }
        }
    }

    Il existe une autre méthode plus simple quand il s'agit de remplir une grande zone avec une image répétée :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    using (Graphics g = Graphics.FromImage(dest))
    {
        using (TextureBrush tbr = new TextureBrush(tile, new Rectangle(96, 80, 16, 16)))
        {
            g.FillRectangle(tbr, 0, 0, 320, 240);
        }
    }

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Points : 390
    Points
    390
    Par défaut
    Bonjour,

    Moi aussi je ne suis pas sur de tout bien comprendre.
    Effectivement la deuxième méthode donnée par ctxnop basée sur un brush défini à partir d'un bitmap est efficace, une autre solution qui permet effectivement de copier un bitmap dans un autre est d'utiliser system.drawing.imaging et lockbits, puis un copymemory de la zone utile dans le nouveau bitmap à l'emplacement voulu, ce n fois.

  8. #8
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Oups il s'agit de tiles de 16 par 16px dsl

    Sinon ctxnop, tu as raison, c'est bien ca que je veux faire.
    Ta première solution est pas mal mais en faite elle oblige à recharger à chaque fois l'image source "tile_maison.bmp" et d'avoir les coordoonées du tile qu'on veut copier (dans ton exemple, tu avais pris : 96*80 le truc violet).

    Or moi, j'ai créé une grille de picturebox de 20 par 14 et imaginons que j'ai fini de créer ma zone grace à l'image 'tile_maison.bmp". Chaque pictubox possède le tile en question et ce que je veux faire c'est sauvegarder l'ensemble des tiles de ma grille dans un SEUL fichier bmp que j'appelle allzone.

    Donc, il me faudrait une fonction avec le prototype suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    'cette fonction copie l'image imageDansPictureBoxCourante dans allZone
    'à la position indiquée par destinationX et destinationY en PIXEL !
     
    'version C# pour toi ^^
    mafct(BITMAP allzone, IMAGE imageDansPictureBoxCourante, int destinationX, int destinationY);
     
    'version vb
    mafct(byval allzone AS BITMAP, byval imageDansPictureBoxCourante as IMAGE, byval destinationX as Integer, byval destinationY as Integer)
    Merci !

    PS : les autres fonctions ne correspondent pas à ce que je veux...

  9. #9
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Je ne comprend pas l'intérêt des picturebox.
    Le picturebox est un contrôle. C'est lourd (ca possède tout pleins de propriétés qui n'ont aucun intérêt ici).

    Le principe même de tiles c'est qu'on ne charge qu'une seule et unique fois l'image contenant les tiles, il ne faut surtout pas s'amuser à la recharger à chaque fois.

    Enregistrer le résultat final sous forme d'image c'est pas super, c'est bien trop lourd.

    Si je reprend ton image maison_tiles.png, faisant 112x96 et sachant qu'un tile fait 16x16, c'est donc déjà à elle toute seule une grille de 7*6 tiles.
    Sachant cela, on considère que les tiles composants l'image sont numéroté (de gauche à droite, puis de haut en bas) en commençant de 0, ce qui donne ceci :

    Code plain : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    +--+--+--+--+--+--+--+
    |00|01|02|03|04|05|06|
    +--+--+--+--+--+--+--+
    |07|08|09|10|11|12|13|
    +--+--+--+--+--+--+--+
    |14|15|16|17|18|19|20|
    +--+--+--+--+--+--+--+
    |21|22|23|24|25|26|27|
    +--+--+--+--+--+--+--+
    |28|29|30|31|32|33|34|
     +--+--+--+--+--+--+--+
     |35|36|37|38|39|40|41|
     +--+--+--+--+--+--+--+

    Ainsi tu peux référencer un élément par son indice et mieux encore, plutot que d'enregistrer une image "résultante" (le allzone) tu enregistres les indices utilisés.
    Tu reconstruira l'image résultante au runtime.
    Deux gros avantages à cette façon de faire :
    - le allzone n'étant plus qu'un tableau de numéro il pèse beaucoup beaucoup moins lourds que l'enregistrement sous forme d'image.
    -> Pour un résultat de 800x600 px ca donne
    (800x600) / 16 = 1875 tiles et 1 octet par tiles = 1875 octets pour le fichier (~1ko).
    en bmp 24bits ca donne 800x600x3 = 1 440 000 octets (~1,38 Mo, une disquette donc)

    - Dans la mesure où le résultat est recalculé au runtime ca veut dire que si demain tu retape un peu ton tile_maison.png pour qu'un tile soit plus propre ou ajouter un détail, etc..., tu n'a rien d'autre à faire, ca sera pris en compte directement. Alors qu'avec ta méthode actuelle il va falloir reconstruire tous les "allzone" contenant ce tile.

  10. #10
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Oui je connait les avantages des tiles mais sur mon jeu, je ne gère pas les maps avec des tiles mais des images complètes. Et vu qu'il y a plus de 20 000 lignes de codes C++, je ne vais pas recoder le jeu pour gérer les tiles
    C'est pour ca qu'il me faut absolument une sortie en BITMAP... même si c'est lourd c'est pas un problème

  11. #11
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Et vu qu'il y a plus de 20 000 lignes de codes C++, je ne vais pas recoder le jeu pour gérer les tiles
    Rohhh petit joueur

    Bon, ok il te faut une image finale, mais ca change quoi ? Je ne vois toujours pas ce qui t'impose les picturebox, t'oblige a recharger l'image tile_maison.png, ou t'embête dans la sauvegarde de l'image finale.

  12. #12
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par ctxnop Voir le message
    Rohhh petit joueur

    Bon, ok il te faut une image finale, mais ca change quoi ? Je ne vois toujours pas ce qui t'impose les picturebox, t'oblige a recharger l'image tile_maison.png, ou t'embête dans la sauvegarde de l'image finale.
    Lol
    Bah j'avais pas d'autres idées que de créer une grille de picturebox, c'est peut être pas l'idéal mais ca marche
    Actuellement, je peux charger et créer un monde, reste plus que la sauvegarde qui foire

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    680
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 680
    Points : 1 183
    Points
    1 183
    Par défaut
    bonsoir,
    j'ai rapidement testé le code d'origine, en inscrivant l'image "maison_tiles.png"
    dans un rectangle dont on indique en gros largeur longueur et non pas la location.
    (Ce qui redimensinne l'image à ces cotes (32/32))
    PictureBox1 contenant "maison_tiles.png" (112/96) pour le test.
    Ca semble fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
        Dim dimTile As Integer = 32
        ' ajoute l'image b dans allimage à la position (0,10) en pixels
        Function test(ByVal source As Bitmap, ByVal part As Image, ByVal x As Integer, ByVal y As Integer) As Bitmap
     
            '*** rapports d'échelle horiz. et verti.
            Dim coeffEchelXx As Double = dimTile / part.Width
            Dim coeffEchelYy As Double = dimTile / part.Height
     
            ' Start with values of parallelogram's vertex.
            Dim x0 As Integer = x
            Dim y0 As Integer = y
            Dim x1 As Integer = CInt(x + part.Width * coeffEchelXx)
            Dim y1 As Integer = y
            Dim x2 As Integer = x
            Dim y2 As Integer = CInt(y + part.Height * coeffEchelYy)
     
            '*** Coordonnées d'au moins 3 angles de l'image.
            Dim points() As Point = {New Point(x0, y0), New Point(x1, y1), New Point(x2, y2)}
            '*** Dessine l'image
     
            ' partB.Save("s_temp_" + x.ToString + "_" + y.ToString + ".bmp")
            Dim g As Graphics = Graphics.FromImage(source)
            'g.DrawImage(part, x, y)
            g.DrawImage(part, points)
            g.Dispose()
     
            ' source.Save("temp_" + x.ToString + "_" + y.ToString + ".bmp")
     
            Return source
        End Function
     
        Dim NBCOLONNE As Integer = 3
        Dim NBLIGNE As Integer = 3
        Dim TY As Integer = dimTile
        Dim TX As Integer = dimTile
     
        Private Sub exporterZone()
            Dim allZone As New Bitmap(NBCOLONNE * TY, NBLIGNE * TX)
            For i = 0 To NBCOLONNE - 1
                For j = 0 To NBLIGNE - 1
                    'récupération de la picturebox correspondante en fct de son nom                
                    Dim p As PictureBox = Me.PictureBox1 'recupererControleParNom("zone_" + i.ToString + "_" + j.ToString)
                    If Not p Is Nothing Then
                        allZone = test(allZone, p.Image, i * dimTile, j * dimTile)
                    End If
                Next
            Next
     
            allZone.Save("final.bmp")
        End Sub

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Points : 390
    Points
    390
    Par défaut
    Bonjour,

    bmp 24bits ca donne 800x600x3 = 1 440 000 octets
    Le 800 en largeur il est choisi exprès ou c'est juste un coup de bol ?
    Car avec 799 ou 801 pixel de large ta formule est fausse, car il faut être aligné sur un multiple de 32bits en largeur d'image sous windows jusqu'à XP après je sais pas il y a sur le sujet une question où je 'ai toujours pas de réponse à propos de Seven (aligné sur 64 ?? ce qui serait logique)

    Pour l'histoire du picturebox etc ... la méthode avec lockbits marche très bien et permet de générer une image finale sans être obligé d'utiliser un picturebox, il suffit de dimensionner un bitmap vide avec les bons paramètres (nb octets par pixels) où l'on viendra coller les pixels de l'image à répéter. Et en matière de rapidité de code vu que c'est du copymemory n fois c'est hyperrapide.

  15. #15
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Citation Envoyé par Geo2A Voir le message
    Bonjour,
    Le 800 en largeur il est choisi exprès ou c'est juste un coup de bol ?
    Car avec 799 ou 801 pixel de large ta formule est fausse, car il faut être aligné sur un multiple de 32bits en largeur d'image sous windows jusqu'à XP après je sais pas il y a sur le sujet une question où je 'ai toujours pas de réponse à propos de Seven (aligné sur 64 ?? ce qui serait logique)
    800x600 c'est une résolution d'écran utilisée quand j'étais jeune ^^'
    Que la formule donne au final 1.38Mo est un pure coup de bol.
    Je n'ai jamais dit que la formule était exacte, juste pour donner une ordre d'idée.
    Normalement, en suivant la norme du bmp, un bmp 24 bits n'est pas aligné sur 32. On le fait généralement purement par simplicité, mais la norme ne l'impose pas.
    Donc 800 x 600 = le nombre de pixels, 3 octets par pixels.

    Si j'avais voulut être rigoureux j'aurais tenus compte du header bmp qui n'est pas si petit, je serais parti sur un bmp avec palette plutot qu'un 24bits, ou meme parti sur un png puisque c'est ce qu'il utilise.

    Sinon, pour en revenir au sujet, je viens de faire un début d'appli qui pourrai te convenir Aspic.
    Tu la trouvera en pièce jointe (c'est du C#, pour pas changer ... faite avec VS2010 ultimate, en winform).
    Fichiers attachés Fichiers attachés

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Points : 390
    Points
    390
    Par défaut
    Bonjour,

    On le fait généralement purement par simplicité, mais la norme ne l'impose pas.
    Hum ... essaye de gérer un DIB avec les API windows sans l'aligner sur 32bits et tu vas avoir de drôles de surprises!

    ou meme parti sur un png puisque c'est ce qu'il utilise.
    Peu importe le format de stockage sur le disque, c'est toujours gérer en mémoire sous forme de DIB.

  17. #17
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Tout d'abord, il n'y a pas que windows dans la vie, ensuite il n'y a pas que les api windows, enfin la norme étant pleinement accessible on peut écrire sa propre lib de bmp.
    Je n'ai pas dit que les api fournies par windows en étaient capable, juste que la norme ne l'impose pas.
    Et la formule concernait le poids sur disque uniquement, aucun intéret de faire la comparaison du format dib en mémoire puisque l'une ou l'autre des deux méthodes donnent le même poids puisque de toute façon le résultat final est toujours une image complète en mémoire.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Points : 390
    Points
    390
    Par défaut
    Bonjour,

    Tout d'abord, il n'y a pas que windows dans la vie
    Excusez moi je croyais être sur un forum VB.NET ...

    ensuite il n'y a pas que les api windows
    Avec un langage utilisant le Framework.NET et d'une manière général l'OS windows en matière de graphisme il n'y a que les API windows, après on les habille comme on veut pour ne pas les voir mais elle sont là.

    Et la formule concernait le poids sur disque uniquement
    Là il y a effectivement un header de 40 octet, puis il faut voir le type de BMP car si c'est du RLE il y a une légère différence entre le poids disque et le poids mémoire idem pour les autres formats entre un tif fax4 de 800 Ko et son image en mémoire de quelques 12Mo il y a une légère différence.

    Pour résumé le titre de la question est "comment COPIER une partie d'une image bitmap dans une autre" Ce que je proposais était effectivement de copier une partie d'image dans une autre, pas de ruser en peignant une partie d'image dans une autre puis d'utiliser les fonctions du framework qui encapsulent les API32 afin d'obtenir une nouvelle image enregistrable sans s'enquiquiner avec toute la théorie sous-jacente ...

    Bon enfin chacubn voit midi à sa porte et la RAD c'est tout de même fait pour ça si non on ferait encore du PUSH CX, DX (bon j'aimais bien ceci dit).

  19. #19
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Le .Net est disponible sur d'autre OS via mono (sachant en plus que mono n'est pas la seule implémentation du CLI autre que celle de Microsoft).
    Il y a tout plein de lib graphique (freeimage, allegro, sdl, etc...) qui offrent toutes des bindings .Net. La plupart étant multi plateforme elle utilisent rarement les api windows mais plutôt une ré-implémentation.

    Ça n'a rien d'une ruse de dessiner une image dans une autre. Ce sont les méthodes qu'on retrouve partout. Et ca fait bien ce qui était demandé dans le titre.

    Je trouve ca tout aussi rapide/pratique de faire ca que de faire un lockbits puis un memcpy puis un unlockbits. Mais je n'ai jamais dit non plus que la méthode du lockbit n'était pas bonne. Libre à toi de reprendre mon TilePainter pour utiliser ta méthode si tu le veux.

    Encore une fois la formule n'était qu'une indication, certainement pas une formule exacte.

    Sinon je ne vois pas trop ce que vient faire le coup du RAD ici.

  20. #20
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par Geo2A Voir le message
    Pour l'histoire du picturebox etc ... la méthode avec lockbits marche très bien et permet de générer une image finale sans être obligé d'utiliser un picturebox, il suffit de dimensionner un bitmap vide avec les bons paramètres (nb octets par pixels) où l'on viendra coller les pixels de l'image à répéter. Et en matière de rapidité de code vu que c'est du copymemory n fois c'est hyperrapide.
    Je suis intéressé par cette méthode donc si tu pouvais poster un petit bout de code (en vb ou C# peut importe ) histoire de voir son implémentation.

    Sinon le code de ctxnop a l'air parfait (pas eu encore le temps de le tester j'ai beaucoup de boulot ) mais je suis sur que c'est ce que j'attends d'après le code que j'ai lu en diagonale ^^ (heureusement que je sais lire le C# merci le C et le C++ [ah les pointeurs ]).
    Merci d'avoir passé un peu de temps à coder un mini-appli pour moi c'est très sympa

    Avezc ca si je m'en sors pas c'est que je suis nul

    EDIT: Dans ton code ctxnop, j'ai une erreur bizarre :
    Type 'TilePainter.GridPictureBox' introuvable. Vérifiez que l'assembly qui contient ce type est référencé. Si ce type est un composant de votre projet de développement, assurez-vous que le projet a été créé comme il se doit à l'aide des paramètres de votre plateforme actuelle ou Any CPU.
    Y'a une assembly a rajouter ou pas ?

Discussions similaires

  1. Utilisation d'une image bitmap dans une DLL
    Par colorid dans le forum Débuter
    Réponses: 5
    Dernier message: 27/02/2009, 16h41
  2. copier une partie d'un fichier texte dans un autre
    Par Valarauko dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 23/10/2007, 22h17
  3. Réponses: 3
    Dernier message: 31/10/2006, 13h20
  4. [VBa-E] Object Ole "image bitmap" dans une Userform?
    Par gootsu dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 10/07/2006, 15h24
  5. Réponses: 6
    Dernier message: 22/12/2004, 12h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo