Erreur: Mémoire insuffisante avec un GetPixel [Résolu]

jimy neutron 491 Messages postés mercredi 1 février 2006Date d'inscription 18 novembre 2016 Dernière intervention - 5 juin 2012 à 14:30 - Dernière réponse : jimy neutron 491 Messages postés mercredi 1 février 2006Date d'inscription 18 novembre 2016 Dernière intervention
- 6 juin 2012 à 09:04
Bonjour,

Voici mon code:
Imports System.Drawing

Public Class Tab
    Inherits System.Windows.Forms.Form

    'API
    Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Integer, ByVal X As Integer, ByVal Y As Integer) As Integer
    Private Declare Function GetDC Lib "user32" (ByVal hWnd As IntPtr) As Integer
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

 
    Private Sub Cmd_ReadPixelC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cmd_ReadPixelC.Click

        ' Dim ThePen As New System.Drawing.Pen(Color.Black)
        Dim SizeH As Long = Cmp.Height
        Dim SizeL As Long = Cmp.Width

        Dim Index As Long = 0
        Dim IndexCol As Long = 0
        Dim IndexLine As Long = 0
        Dim NivGrayC As Integer = 0
        Dim colorVal As Integer = 0
        Dim PRed As Integer = 0
        Dim PGreen As Integer = 0
        Dim PBlue As Integer = 0
        Dim SomPxC As Long = 0

        Me.LabEncours.Visible = True

        'Scan de l'image
        For IndexCol = 0 To SizeL
            For IndexLine = 0 To SizeH

                colorVal = GetPixel(GetDC(0&), Cmp.Left + IndexCol, Cmp.Top + IndexLine)
                PRed = colorVal And &HFF
                PGreen = (colorVal And &HFF00) / 256
                PBlue = (colorVal And &HFF0000) / 65536
                NivGrayC = (77 * PBlue + 151 * PGreen + 28 * PRed) / 256
                Index = Index + 1
                SomPxC = SomPxC + NivGrayC
            Next
        Next
        Me.LabEncours.Visible = False
        Me.LabC_Gray.Text = (SomPxC / Index).ToString

        Call ReleaseDC(0, GetDC(0&))
    End Sub
End Class



En fait j'ai un Form (Tab) qui propose le show par un bouton d'un autre form (appelé "Cmp" dans le code.)
Et un autre bouton pour scanner tous les pixels de l'écran sous "Cmp".

Le problème, c'est que cela fonctionne bien, mais une seule fois.
Si je relance, même plusieurs minutes plus tard, l'appli plante en "Mémoire insuffisante" ou "La référence d'objet n'est pas définie à une instance d'un objet"

Auriez-vous une idée?

Je précise que je suis en VB 2010 sous framework 3.5 (pas le choix)

Merci d'avance ;)
Jimy

Pensez: Réponse acceptée
'**********************************************
Afficher la suite 

Votre réponse

7 réponses

Meilleure réponse
ucfoutu 18039 Messages postés lundi 7 décembre 2009Date d'inscriptionContributeurStatut 11 avril 2018 Dernière intervention - 5 juin 2012 à 14:43
3
Merci
Bonjour,
1) Ta déclaration de la fonction ReleaseDC est en type Long ! A corriger !
2) Essaye d'éviter les expressions du genre :
 GetPixel(GetDC(0&)....

Call ReleaseDC(0, GetDC(0&))

extrait ton GetDc(0) u ne seule fois ===>> en toto,
Puis :
GetPixel(toto, ....
Call ReleaseDC(0, toto)

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" pour faciliter les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement vous dire ce qu'elle contient. Je n'interviendrai qu'en cas de nécessité de développ

Merci ucfoutu 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 68 internautes ce mois-ci

Commenter la réponse de ucfoutu
Meilleure réponse
Utilisateur anonyme - 5 juin 2012 à 23:26
3
Merci
Tu peux très bien recopier sur un bitmap une portion d'écran afin d'en analyser l'un de ses pixels.
Voici un petit code commenté pour l'exemple :
'déclaration d'un bitmap 32 millions couleurs de 50 pixels de côté
Dim b As New Bitmap(50, 50, Imaging.PixelFormat.Format32bppArgb)
'outils de dessin sur le bitmap
Dim g As Graphics = Graphics.FromImage(b)
'recopie d'une portion d'écran sur le bitmap depuis les coordonnées screen x 100 et y 100
g.CopyFromScreen(100, 100, 0, 0, New Size(b.Width, b.Height), CopyPixelOperation.SourceCopy)
'analyse du pixel du centre (50/2)
Dim couleur_lue As Color = b.GetPixel(25, 25)
'affichage des composantes RVB de la couleur du pixel
MessageBox.Show(String.Format("rouge={0}, vert={1}, bleu={2}", couleur_lue.R, couleur_lue.G, couleur_lue.B))

Merci Utilisateur anonyme 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 68 internautes ce mois-ci

Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 5 juin 2012 à 14:38
0
Merci
Bonsoir,

Pourquoi ne pas avoir utilisé les outils inclus dans le framework (voir Bitmap et sa méthode GetPixel) plutôt que des API ?
Commenter la réponse de Utilisateur anonyme
jimy neutron 491 Messages postés mercredi 1 février 2006Date d'inscription 18 novembre 2016 Dernière intervention - 5 juin 2012 à 15:08
0
Merci
Merci de vos réponses,

Ucfoutu, je regarde cela de suite. :)

Banana32, je ne travaille pas sur une image que j'ouvre dans un picturebox (jpg ou autres) mais directement sur l'image envoyée par une camera industrielle d'une autre appli.




Je dois comparer la moyenne des niveaux de gris des deux images.
Je scanne donc chaque pixels de l'image de reference, une seule fois.
Puis pour chaque image en cours, je fais de même et compare les moyennes.

Jimy

Pensez: Réponse acceptée
'**********************************************
Commenter la réponse de jimy neutron
NHenry 14250 Messages postés vendredi 14 mars 2003Date d'inscription 10 août 2018 Dernière intervention - 5 juin 2012 à 19:09
0
Merci
Bonjour,

Comment tu mets à jour ta PictureBox ?

De mémoire, quand j'avais fait cela, je mettais en place un système pour demander explicitement le rafraichissement.

Sinon, je pense qu'il y a un moyen de copier le contenu d'un bitmap.

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, celui-ci pour bien poser votre question ou encore celui-ci pour les PFE et autres exercices.[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : ).[*]En VB.NET pensez à activer Option Explicit et Option Strict (propriété du projet) et à retirer l'import automatique de l'espace de nom Microsoft.VisualBasic (onglet Références dans les propriétés du projet).[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés/list
---
Mon site
Commenter la réponse de NHenry
jimy neutron 491 Messages postés mercredi 1 février 2006Date d'inscription 18 novembre 2016 Dernière intervention - 5 juin 2012 à 21:17
0
Merci
Salut NHenry

Comme expliqué au dessus, les deux images ci-dessus sont affichées par une application industrielle, je n'ai pas accès aux fichiers pour les charger dans des pictureboxs.
La seule solution est de venir scanner les deux images telles quelles, puis les comparer. J'utilise donc un form, avec une opacité à 20%, placée au dessus et je scanne chaque pixel, je le fais pour l'image de référence, puis pour l'image en cours et je compare.
Mon code fonctionne si je ne l’exécute qu'une fois. A la seconde exécution, l'appli plante.

Jimy

Pensez: Réponse acceptée
'**********************************************
Commenter la réponse de jimy neutron
jimy neutron 491 Messages postés mercredi 1 février 2006Date d'inscription 18 novembre 2016 Dernière intervention - 6 juin 2012 à 09:04
0
Merci
Merci Ucfoutu, c'est bien l'appel du GetDC à répétition qui posait problème.

Banana32, ton idée est séduisante, je vais creuser. Merci aussi! ;)


Jimy

Pensez: Réponse acceptée
'**********************************************
Commenter la réponse de jimy neutron

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.