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

Lazarus Pascal Discussion :

Chargement et affichage de grandes images


Sujet :

Lazarus Pascal

  1. #1
    Membre averti
    Chargement et affichage de grandes images
    Bonsoir,

    Mon environnement:
    Lazarus version: 2.1.0
    Lazarus svn revision: 63204
    Lazarus build date: 2020/05/22
    Lazarus was compiled for i386-win32
    Lazarus was compiled with fpc 3.3.1

    et ci-joint un petit projet pour montrer les difficultés rencontrées lors du chargement et l'affichage d'une grande image.
    Dans ce projet les références pour télécharger:
    La grande image, un jpg de 37.03 Mo, définition 15410X9910 px X 24 bpp soit un bitmap théorique d'environ 437 Mo
    Une version réduite à l'échelle 1/2 de la même image.
    L'image étant beaucoup plus grande que la fiche (et l'écran), est placée dans une scrollbox qui permet d'en visualiser la totalité à l'aide des barres de défilement.
    Un bouton permet de charger le fichier image dans le TImage.
    1er essai avec uniquement Image1.Picture.LoadFromFile(Fichier);
    Le chargement de la grande image est arrêté par une erreur "out of memory" alors que la mémoire occupée par l'application (vue dans le gestionnaire de tâches) arrive à 1.2 Go.
    L'image réduite se charge correctement, mais la mémoire occupée par l'image (observée par le même moyen) correspond à 8 octets par pixel au lieu des 3 théoriques. Ensuite le déplacement de l'image dans la scrollbox à l'aide des barres de défilement manque nettement de fluidité.
    D'où vient l'erreur?
    Le chargement du fichier de l'image réduite dans un TBGRABitmap avant de la transférer l'image dans le TImage règle les problèmes: l'image n'occupe que 4 octets/pixel et les déplacements sont bien plus fluides.
    Mais pour la grande image, rien ne s'affiche, même pas le message d'erreur?

    Second problème: en utilisant les événements onmousedown et onmousemove du TImage, un premier clic droit de la souris mémorise le point de départ d'un trait qui se prolonge ensuite jusqu'à la position en cours de la souris. Ce "dessin" s'arrête avec un second clic droit de la souris.
    Si après le démarrage de l'application et le chargement de l'image, le premier clic droit a lieu dans l'espace affiché avant tout déplacement de l'image dans la scrollbox, tout fonctionne parfaitement. On peut ensuite déplacer l'image et recommencer le "dessin" du trait sans aucune anomalie.
    Mais si après le démarrage de l'application et le chargement de l'image, cette image est déplacée avant le premier clic droit, le trait ne se trace pas à l'endroit prévu, mais est décalé, comme si les X et Y des événements OnMouse étaient tous décalés, et ce décalage correspond à la position des barres de défilements lors du premier clic. Il reste identique pendant toute la session, même si on recharge une autre image.
    Il me semble donc qu'il y a une anomalie dans l'initialisation de ces coordonnées.
    Y a-t-il un moyen correct de les initialiser correctement, autrement qu'en appliquant un décalage égal aux positions des barres lors du premier clic de la session?

    André

  2. #2
    Membre averti
    Bonjour,

    Correction de 2 erreurs dans la démo jointe à mon message:
    Activer le DoubleBuffered de la forme.
    Le tracé de la ligne: Line(SBMX,SBMY,X,Y); (erreur de copier coller pour la démo dans le précédent).

    X et Y sont les coordonnées dans le canevas de l'image, alors que je dessine dans le canevas de la scrollbox. Tout se passe comme si les origines des 2 canevas n'étaient pas les mêmes, et initialisées lors du premier clic.

    André

    PS: oubliez ce problème, je crois avoir compris. L'origine du canevas de la scrollbox est toujours l'angle en haut à gauche de la partie visible, pas pour l'image.

  3. #3
    Expert éminent sénior
    Bonjour,
    Citation Envoyé par alanglet Voir le message
    La grande image, un jpg de 37.03 Mo, définition 15410X9910 px X 24 bpp soit un bitmap théorique d'environ 437 Mo
    chez moi, avec une simple calculatrice et hors de tout Lazarus ou autre,
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    15410 × 9910 = 152713100

    je rajoute les séparateurs des milliers pour que ça soit plus lisible : 152 713 100

    et ce résultat × 24 = 3665114400,
    soit 3 665 114 400
    soit 3,66 Go, et tu exploses tout avec une machine 32 bits.

    PS : d'où sort ton bitmap théorique d'environ 437 Mo ?
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  4. #4
    Membre éclairé
    Citation Envoyé par Jipété Voir le message
    et ce résultat × 24 = 3665114400, ...
    N'aurais-tu pas tendance à confondre "bits" et "octets"

    152 713 100 x 3 = 458 Mo.

    Cordialement.

    Pierre.

  5. #5
    Membre averti
    Non, pas de calculatrice, mais lorsque j'étais en primaire on faisait beaucoup de calcul mental, et pendant des études d'ingé, la règle à calcul ne donnait pas les puissances de 10.
    Je confirme bien le problème de décalage du dessin sur le canevas de la scrollbox. Tout se passe comme si l'origine du canevas de la SB n'était défini que lors du premier dessin. J'ai contourné le problème en définissant un décalage lors du premier clic gauche de la session. Ce décalage est égal à la position du point origine de la SB sur l'image, donné par les positions des barres de défilements à ce moment là.

    André

  6. #6
    Expert éminent sénior
    Citation Envoyé par ChPr Voir le message
    N'aurais-tu pas tendance à confondre "bits" et "octets"
    Ah ben vi !



    Faut dire qu'à 9 h 45 je n'étais pas bien réveillé, On dort mal, avec cette chaleur.

    Toutes mes excuses et je m'en vais sur la pointe des pieds…
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  7. #7
    Membre expert
    Salut André

    Citation Envoyé par alanglet Voir le message
    Bonsoir,
    ...
    et ci-joint un petit projet pour montrer les difficultés rencontrées lors du chargement et l'affichage d'une grande image.
    Dans ce projet les références pour télécharger:
    La grande image, un jpg de 37.03 Mo, définition 15410X9910 px X 24 bpp soit un bitmap théorique d'environ 437 Mo
    Une version réduite à l'échelle 1/2 de la même image.
    L'image étant beaucoup plus grande que la fiche (et l'écran), est placée dans une scrollbox qui permet d'en visualiser la totalité à l'aide des barres de défilement.
    Un bouton permet de charger le fichier image dans le TImage.
    1er essai avec uniquement Image1.Picture.LoadFromFile(Fichier);
    Ton projet dans le zip est corrompu
    Le lien de téléchargement de l'image ne fonctionne pas

    La taille en octet de ton image brut en mémoire devrait être de 15410 x 9910 x 3 = 458 139 300 octets soit environ 437 Mo théoriquement

    Citation Envoyé par alanglet Voir le message

    Le chargement de la grande image est arrêté par une erreur "out of memory" alors que la mémoire occupée par l'application (vue dans le gestionnaire de tâches) arrive à 1.2 Go.
    1.2 go c'est la mémoire libre qu'il te reste avant chargement ?
    De combien de RAM disposes tu au total ?

    Citation Envoyé par alanglet Voir le message

    L'image réduite se charge correctement, mais la mémoire occupée par l'image (observée par le même moyen) correspond à 8 octets par pixel au lieu des 3 théoriques. Ensuite le déplacement de l'image dans la scrollbox à l'aide des barres de défilement manque nettement de fluidité.
    D'où vient l'erreur?

    Le chargement du fichier de l'image réduite dans un TBGRABitmap avant de la transférer l'image dans le TImage règle les problèmes: l'image n'occupe que 4 octets/pixel et les déplacements sont bien plus fluides.
    Mais pour la grande image, rien ne s'affiche, même pas le message d'erreur?

    Lazarus/FPC stocke les pixels en 64bits d'ou 8 octets soit 15410 x 9910 x 8 = environ 1.165go. C'est plutôt bizarre normalement dans le TPicture.TBitmap du TImage l'image devrait être stockée sur 3 ou 4 octets maximum

    J'ai fait un petit test identique au tiens, une scrollbox, un TImage et un Bouton pour charger cette image JPG de 39137x22279 réduite à 30000x17078 car l'original se charge mais ne s'affiche pas
    Cette dernière a donc une taille théorique de 30000 x 17078 x 3 = environ 1.465go

    Memoire avant chargement


    Memoire après chargement


    On peut noter que le charment de l'image dans l'application test utilise environ 4go de mémoire.
    Ce qui correspond à environ 30000 x 17078 x 8 = 3.908go

    En 32bit la mémoire n'est pas gérée de la même manière qu'en 64bit l'allocation d'un bloc mémoire est limité à 2go contre 4go en théorie.
    Si tu compiles en 64bit, cela devrait résoudre ton problème.

    Autre petite chose, la gestion des bitmap sous Lazarus n'est vraiment pas top d'ou cette surcharge en mémoire notamment.

    Une solution serait d'utiliser ma bibliothèque BZScene

    L'image réduite est chargée sans aucun problème dans mon application.
    Et voila l'image originale (39137x22279) chargée, moyennant quelques petites modifications pour réduire l'utilisation en mémoire. A cause de plusieurs tampons intermédiaires utilisés en interne dans mon application, qui saturaient la mémoire



    Dans tous les cas grâce au composant TBZImageViewer (qui gère les déplacements, le zoom, le redimensionnement...), sans tampons intermédiaires qui pourraient saturer la mémoire, tu seras en mesure de charger tes "très grandes images"

    Si tu as des questions sur l'utilisation de BZScene n'hésites pas
    Par contre je n'ai pas testé ma bibliothèque intensivement en 32bit, le mieux est donc de compiler en 64bit et surtout d'utiliser la version FPC 3.2 maximum pour le moment pour des raisons de compatibilité.

    Le manque de fluidité vient du fait de la taille de l'image et de la façon dont la scrollbox/timage fonctionnent tu as 2 contrôles, donc 2 rafraîchissements effectifs, de plus le Timage intégré occupant la totalité de la surface de l'image, c'est donc toute l'image qui est rafraîchit en premier, et non pas juste la partie visible.


    Citation Envoyé par alanglet Voir le message


    Second problème: en utilisant les événements onmousedown et onmousemove du TImage, un premier clic droit de la souris mémorise le point de départ d'un trait qui se prolonge ensuite jusqu'à la position en cours de la souris. Ce "dessin" s'arrête avec un second clic droit de la souris.
    Si après le démarrage de l'application et le chargement de l'image, le premier clic droit a lieu dans l'espace affiché avant tout déplacement de l'image dans la scrollbox, tout fonctionne parfaitement. On peut ensuite déplacer l'image et recommencer le "dessin" du trait sans aucune anomalie.
    Mais si après le démarrage de l'application et le chargement de l'image, cette image est déplacée avant le premier clic droit, le trait ne se trace pas à l'endroit prévu, mais est décalé, comme si les X et Y des événements OnMouse étaient tous décalés, et ce décalage correspond à la position des barres de défilements lors du premier clic. Il reste identique pendant toute la session, même si on recharge une autre image.
    Il me semble donc qu'il y a une anomalie dans l'initialisation de ces coordonnées.
    Y a-t-il un moyen correct de les initialiser correctement, autrement qu'en appliquant un décalage égal aux positions des barres lors du premier clic de la session?

    André
    Pour solutionner ton problème tu n'as pas besoin de tenir compte des déplacements de la scrollbox

    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
    procedure TForm1.Image1MouseMove(Sender : TObject; Shift : TShiftState; X, Y : Integer);
    begin
     
      if MesureEnCours then
      begin
        SB.Repaint;
        Screen.Cursor:=crCross;
        with SB.Canvas do
        begin
          Pen.Style:=psSolid;
          Pen.Color:=clBlack;
          Pen.Width:=2;
          Line(SBMX,SBMY, X,Y);
        end;
      end;
    end;


    A+

    Jérôme

    [EDIT] tu peux aussi consulté ce fil de discussion pour plus d'infos : https://www.developpez.net/forums/d1...ssible-ouvrir/
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  8. #8
    Membre averti
    Merci pour vos réponses.

    Bizarre pour le zip corrompu. Je viens de le télécharger sur ce site et de l'ouvrir sans difficultés

    Mon PC Win 64b dispose de 8 Go de RAM. Il en reste 4.8 avant chargement et 3.6 à l'apparition du message Out of memory.
    Concernant ta remarque sur la taille de 39137 que tu as dû réduire à 30000, il me semble avoir lu quelque part que les dimensions d'un bitmap étaient limitées à 32767 parce que c'est un smallint, mais peut-être n'est-ce valable qu'en 32b?
    Cette application est développée en 32b simplement pour des raisons de compatibilité avec une autre application dont elle est une sorte de "périphérique".
    J'avais jeté un rapide coup d'œil sur BZScene mais son utilisation m'a paru plus complexe que le TBGRABitmap. Je reverrai ça plus tard.
    Le tracé sur le canevas de la SB, qui n'utilise que les coordonnées X Y de la souris sur l'image fonctionne tant que les origines de l'image et de la SB sont confondues. Mais lorsque l'image a été déplacée dans la SB ce n'est plus le cas, l'origine de l'image est hors du cadre visible de la SB. L'origine du canevas de la BS reste l'angle supérieur gauche de sa partie visible.
    Aux coordonnées XY du point sur l'image, il faut donc déduire la position des barres de défilement pour obtenir la position du point sur le canevas de la SB.
    C'est ce que je fais normalement. Mais je me suis aperçu que ça n'est pas suffisant car il y a un autre décalage qui est la position du point 0 de la SB dans l'image (=les positions des barres de défilement) au moment du premier tracé dans l'application, décalage qui est conservé tant que l'application reste ouverte. C'est ce décalage qui me paraît anormal.
    Il y aurait bien la solution de tracer sur le canevas de l'image au lieu de celui de la SB, mais il faudrait gérer l'effacement du trait sur l'image.

    André

  9. #9
    Membre expert
    Citation Envoyé par alanglet Voir le message
    Merci pour vos réponses.

    Bizarre pour le zip corrompu. Je viens de le télécharger sur ce site et de l'ouvrir sans difficultés
    Je me suis mal exprimé c'est le projet en lui même, il ne s'ouvre pas dans mon Lazarus 2.0.8, le lpi ne contient pas l'unit1 et le lpr. Bref pas bien grave car c'est rapide à refaire.

    Citation Envoyé par alanglet Voir le message

    Mon PC Win 64b dispose de 8 Go de RAM. Il en reste 4.8 avant chargement et 3.6 à l'apparition du message Out of memory.
    Hum il faudrait débogguer en pas à pas pour voir u se situe exactement cette erreur et regarder dans le même temps l'utilisation de la mémoire. Car si à ce moment il tenete d'allouer 4Go cette erreur serait normale

    Citation Envoyé par alanglet Voir le message

    Concernant ta remarque sur la taille de 39137 que tu as dû réduire à 30000, il me semble avoir lu quelque part que les dimensions d'un bitmap étaient limitées à 32767 parce que c'est un smallint, mais peut-être n'est-ce valable qu'en 32b?
    Il faudrait vérifier dans le code de FPC/Lazarus pour identifier le type exacte.

    Citation Envoyé par alanglet Voir le message

    Cette application est développée en 32b simplement pour des raisons de compatibilité avec une autre application dont elle est une sorte de "périphérique".
    Peux tu nous en dire plus ?

    Citation Envoyé par alanglet Voir le message

    J'avais jeté un rapide coup d'œil sur BZScene mais son utilisation m'a paru plus complexe que le TBGRABitmap. Je reverrai ça plus tard.
    C'est une fausse idée c'est même notamment plus simple pour appliquer des traitements et autres filtres sur une image

    Exemple dans un projet :
    1) Tu places un TBZImageViewer.
    2) Tu ajoutes les unités nécessaires supplémentaires suivant ce que tu souhaites faire dans le uses. Usuellement BZColors, BZGraphic, BZBitmap, BZBitmapIO. Cette dernière est une unité de convenance permettant d'ajouter le support aux différents formats (bmp, tga, pcx, xpm, pixmap, gif, jpeg, png, webp)
    3) Dans le code pour charger l'image il suffit de faire :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ImageViewer1.Picture.LoadFromFile('MonImage.jpg')


    C'est tout

    Si tu n'utilises pas le TBZImageViewer, il suffit de rajouter le paquet BZScene_Image_RT dans les dépendances du projet. Déclarer les unités
    et enfin pour charger une image dans un TBZBitmap c'est comme BGRABitmap

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Var
      MonBmp : TBZBitmap;
    begin
      MonBmp := TBZBitmap.Create;
      MonBmp.LoadFromFile('MonImage.png');
      MonBmp.ColorFilter.GrayScale(); // conversion en niveau de gris
      MonBmp.Transformation.Resample(64,64,ifmLanczos3, true); // redimensionnement par sur-échantillonnage et conservation du ratio
      //...
      MonBmp.DrawToCanvas(Panel1.Canvas, Panel1.ClientRect); // Affichage sur un panel
    end;


    Citation Envoyé par alanglet Voir le message

    Le tracé sur le canevas de la SB, qui n'utilise que les coordonnées X Y de la souris sur l'image fonctionne tant que les origines de l'image et de la SB sont confondues. Mais lorsque l'image a été déplacée dans la SB ce n'est plus le cas, l'origine de l'image est hors du cadre visible de la SB. L'origine du canevas de la BS reste l'angle supérieur gauche de sa partie visible.
    Aux coordonnées XY du point sur l'image, il faut donc déduire la position des barres de défilement pour obtenir la position du point sur le canevas de la SB.
    C'est ce que je fais normalement. Mais je me suis aperçu que ça n'est pas suffisant car il y a un autre décalage qui est la position du point 0 de la SB dans l'image (=les positions des barres de défilement) au moment du premier tracé dans l'application, décalage qui est conservé tant que l'application reste ouverte. C'est ce décalage qui me paraît anormal.
    Il y aurait bien la solution de tracer sur le canevas de l'image au lieu de celui de la SB, mais il faudrait gérer l'effacement du trait sur l'image.

    André
    La taille du Canvas de la SB est la même que le TImage. Je doit partir je ferai quelques tests plus tard

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  10. #10
    Membre averti
    J'ai voulu tester le BzBitmap, mais sans doute un problème de compatibilité avec les versions de FPC et Lazarus que j'utilise (mis à jour depuis SVN, voir mon 1er message), sélection des 25 erreurs (en fait 3) lors de la compilation:
    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
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1340,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..8] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1341,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..24] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1342,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..48] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1399,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..8] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1400,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..24] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(1401,45) Error: (4001) Incompatible types: got "TBZConvolutionFilter..Array[0..48] Of Single" expected "{Dynamic} Array Of Single"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6625,72) Error: (4025) Incompatible type for arg no. 6: Got "Boolean", expected "TBZConvolutionFilterMode"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6626,72) Error: (4025) Incompatible type for arg no. 6: Got "Boolean", expected "TBZConvolutionFilterMode"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6627,72) Error: (4025) Incompatible type for arg no. 6: Got "Boolean", expected "TBZConvolutionFilterMode"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6669,104) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6673,102) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6680,104) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6684,102) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6691,102) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6695,100) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6702,103) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6706,101) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6713,103) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6717,101) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6724,105) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6728,103) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6735,101) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6739,99) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6746,104) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    D:\freepascal\composants\BZScene\Source\Image\BZBitmap.pas(6750,102) Error: (4025) Incompatible type for arg no. 5: Got "LongInt", expected "Boolean"
    BZBitmap.pas(10209) Fatal: (10026) There were 25 errors compiling module, stopping


    Lors du chargement direct dans le Picture de la grande image, l'erreur intervient dans win32proc.pp, fonction GetBitmapBytes, ligne 1272 exécution de aWinBmp.CopyImageData. Dans cette dernière fonction implémentée dans lazutils\graphtype.pp le dépassement intervient ligne 306 lors de l'allocation mémoire par GetMem(Adestination,Asize). Il est sans doute là le problème, s'il faut allouer une seconde fois la même taille mémoire...

    Bonne soirée
    André

  11. #11
    Membre expert
    Citation Envoyé par alanglet Voir le message
    J'ai voulu tester le BzBitmap, mais sans doute un problème de compatibilité avec les versions de FPC et Lazarus que j'utilise (mis à jour depuis SVN, voir mon 1er message), sélection des 25 erreurs (en fait 3) lors de la compilation:
    Oui c'est du que BZScene est compatible jusqu'a FPC 3.2 comme je le disais. pour les versions au dessus, je n'ai fait aucun test.
    D'ou ces erreurs d'incompatibilité. Pour plus de stabilité avec Lazarus les versions stables de FPC 3.0.4 et FPC 3.2 sont recommandées
    D'après tes messages d'erreurs, il semblerai que FPC 3.3.1 est quelques soucis avec la directive Overload actuelle.

    Chez moi j'utilise Lazarus 2.0.8 avec FPC 3.2 sous Windows et sous Linux Lazarus 2.0.8 avec FPC 3.0.4.

    Citation Envoyé par alanglet Voir le message

    Lors du chargement direct dans le Picture de la grande image, l'erreur intervient dans win32proc.pp, fonction GetBitmapBytes, ligne 1272 exécution de aWinBmp.CopyImageData. Dans cette dernière fonction implémentée dans lazutils\graphtype.pp le dépassement intervient ligne 306 lors de l'allocation mémoire par GetMem(Adestination,Asize). Il est sans doute là le problème, s'il faut allouer une seconde fois la même taille mémoire...

    Bonne soirée
    André
    Si l'erreur intervient lors de l'allocation c'est qu'a ce moment tu n'as plus assez de mémoire libre pour continuer, et dans ce cas tu ne peux rien faire, mise à part rajouter des barrettes.

    Pour ton traçage de ligne essayes comme ceci :

    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
    procedure TForm1.Image1MouseDown(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
    begin
      if Button=mbRight then
       begin
         if MesureEnCours then
         begin
           MesureEnCours:=False;
           Screen.Cursor:=crDefault;
         end
         else
         begin
           SBMX:=X;
           SBMY:=Y;
     
           MesureEnCours:=True;
           Screen.Cursor:=crCross;
         end;
       end;
    end;
     
    procedure TForm1.Image1MouseMove(Sender : TObject; Shift : TShiftState; X, Y : Integer);
    begin
     
      if MesureEnCours then
      begin
        SB.Repaint;
        Screen.Cursor:=crCross;
        with SB.Canvas do
        begin
          Pen.Style:=psSolid;
          Pen.Color:=clBlack;
          Pen.Width:=2;
          Line(SBMX - SB.HorzScrollBar.Position, SBMY - SB.VertScrollBar.Position, X - SB.HorzScrollBar.Position,Y - SB.VertScrollBar.Position);
        end;
      end;
    end;


    Bonne soirée

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  12. #12
    Membre averti
    Bonjour,

    Citation Envoyé par BeanzMaster Voir le message
    Si l'erreur intervient lors de l'allocation c'est qu'a ce moment tu n'as plus assez de mémoire libre pour continuer, et dans ce cas tu ne peux rien faire, mise à part rajouter des barrettes.
    Sauf que travaillant en 32b, c'est la capacité d'adressage de 2Go qui risque d'être atteinte.
    Pour voir ça, j'ai tracé d'un peu plus prêt le chargement. Je me suis aperçu qu'avant d'arriver à ce GetMem qui provoque l'erreur, le fichier avait été chargé, que la mémoire occupée était de 1 234 756 ko (3 Mo pour l'application avant chargement) et que le GetMem demandait l'allocation de 610 842 400 octets supplémentaires (sans doute pour l'affichage?). On arrive bien prêt de la limite des 2 Go...

    Citation Envoyé par BeanzMaster Voir le message
    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
    procedure TForm1.Image1MouseMove(Sender : TObject; Shift : TShiftState; X, Y : Integer);
    begin
      if MesureEnCours then
      begin
        SB.Repaint;
        Screen.Cursor:=crCross;
        with SB.Canvas do
        begin
          Pen.Style:=psSolid;
          Pen.Color:=clBlack;
          Pen.Width:=2;
          Line(SBMX - SB.HorzScrollBar.Position, SBMY - SB.VertScrollBar.Position, X - SB.HorzScrollBar.Position,Y - SB.VertScrollBar.Position);
        end;
      end;
    end;
    C'est exactement ce que j'ai fait au départ. Ça marge très bien si le premier clic (début du tracé) après le démarrage de l'application est fait alors que les barres de défilement sont en position zéro.
    Pour que ce soit plus clair, j'ai utilisé Line(P1,P2) pour effectuer le tracé, ClientToParent pour la conversion des coordonnées Image en coordonnées ScroolBox (équivalent à la soustraction de la position des barres), et affiché les différentes coordonnées dans la barre de titre.
    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
    procedure TForm1.Image1MouseMove(Sender:TObject;Shift:TShiftState;X,Y:Integer);
    var
      P1,P2:TPoint;
    begin
      P1.X:=SBMX;
      P1.Y:=SBMY;
      P1:=Image1.ClientToParent(P1,SB);
      P2.X:=X;
      P2.Y:=Y;
      P2:=Image1.ClientToParent(P2,SB);
      Caption:='X='+IntToStr(X)+' Y='+IntToStr(Y)+'   P1.X='+IntToStr(P1.X)+' P1.Y='+IntToStr(P1.Y)+'   P2.X='+IntToStr(P2.X)+' P2.Y='+IntToStr(P2.Y);
      if MesureEnCours then
      begin
        SB.Repaint;
        Screen.Cursor:=crCross;
        with SB.Canvas do
        begin
          Pen.Style:=psSolid;
          Pen.Color:=clBlack;
          Pen.Width:=2;
          Line(P1,P2);
        end;
      end;
    end;

    Puis après l'ouverture de l'application et le chargement de l'image, j'ai déplacé l'image avec les barre de défilement avant d'effectuer le premier clic.
    Comme le tracé n'apparaît pas, j'ai remis les barres de défilement au point 0. Et voici ce qui s'affiche:

    Vous pouvez voir que le tracé ne s'effectue pas entre les points P1 et P2, mais qu'il est décalé.
    Ce décalage c'est la position des barres lors du premier clic de la session.
    La preuve dans la version suivante (utilisant des TPoint pour être plus clair), où les positions des barres au premier clic droit de la session sont mémorisées dans le point Pd représentant le décalage. Le point Pd est ensuite ajouté à toutes les coordonnées avant tracé. Mais je considère que cette opération n'est qu'une façon de contourner une anomalie.
    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
    procedure TForm1.Image1MouseDown(Sender:TObject;Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
    begin
      if Button=mbRight then
      begin
        if MesureEnCours then
        begin
          MesureEnCours:=False;
          Screen.Cursor:=crDefault;
        end
        else
        begin
          if PremiereMesure then //PremiereMesure Boolean initialisé à True dans FormCreate
          begin
            Pd.X:=SB.HorzScrollBar.Position;
            Pd.Y:=SB.VertScrollBar.Position;
            PremiereMesure:=False;
          end;
          P0.X:=X;
          P0.Y:=Y;
          MesureEnCours:=True;
          Screen.Cursor:=crCross;
        end;
      end;
    end;
     
    procedure TForm1.Image1MouseMove(Sender:TObject;Shift:TShiftState;X,Y:Integer);
    var
      P1,P2:TPoint;
    begin
      if MesureEnCours then
      begin
        SB.Repaint;
        Screen.Cursor:=crCross;
        P1:=Image1.ClientToParent(P0+Pd,SB);
        P2.X:=X;
        P2.Y:=Y;
        P2:=Image1.ClientToParent(P2+Pd,SB);
        with SB.Canvas do
        begin
          Pen.Style:=psSolid;
          Pen.Color:=clBlack;
          Pen.Width:=2;
          Line(P1,P2);
        end;
      end;
    end;


    André

  13. #13
    Membre averti
    Bonjour,

    Une solution plus simple pour contourner ce problème de canevas de ScrollBox baladeur: mettre l'image dans un panneau sans bord et mettre ce panneau, AllClient et AutoSize dans la ScrollBox. On peut alors effectuer le tracé sur le canevas panneau au lieu du canevas de la ScrollBox, sans effectuer de correction des coordonnées de la souris sur l'image.

    André

  14. #14
    Membre expert
    Citation Envoyé par alanglet Voir le message
    Bonjour,

    Une solution plus simple pour contourner ce problème de canevas de ScrollBox baladeur: mettre l'image dans un panneau sans bord et mettre ce panneau, AllClient et AutoSize dans la ScrollBox. On peut alors effectuer le tracé sur le canevas panneau au lieu du canevas de la ScrollBox, sans effectuer de correction des coordonnées de la souris sur l'image.

    André
    Bonjour tu peux directement utiliser le canvas du TImage.

    Citation Envoyé par alanglet Voir le message
    Bonjour,


    Sauf que travaillant en 32b, c'est la capacité d'adressage de 2Go qui risque d'être atteinte.
    Pour voir ça, j'ai tracé d'un peu plus prêt le chargement. Je me suis aperçu qu'avant d'arriver à ce GetMem qui provoque l'erreur, le fichier avait été chargé, que la mémoire occupée était de 1 234 756 ko (3 Mo pour l'application avant chargement) et que le GetMem demandait l'allocation de 610 842 400 octets supplémentaires (sans doute pour l'affichage?). On arrive bien prêt de la limite des 2 Go...
    C'est bizarre car la capacité d'adressage c'est par bloc. 610 842 400 octets supplémentaires c'est environ 583 mo. On est encore loin des 2Go Avant d'arriver à ce GetMem quelle est la quantité de mémoire encore disponible ?
    De plus 1 234 756 ko =environ 1206 Mo + 583 + 3 = 1789 Mo, il y a encore 211 Mo avant d'atteindre les 2Go

    Faudrait faire une petite app de test avec GetMem et voir jusqu’à combien de Go on peut allouer à un pointer et combien de tampons dans la limite de la mémoire disponible.
    Je vais tenter de faire un petit test c'est après-midi dans ce sens

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  15. #15
    Membre averti
    Bonjour,

    Citation Envoyé par BeanzMaster Voir le message
    Bonjour tu peux directement utiliser le canvas du TImage.
    Exact et ce serait plus simple les coordonnées de la souris sur l'image retournées par les événements OnMouse n'ayant pas à être transformées. Mais il faudrait alors gérer aussi l'effacement du trait précédent sur l'image à chaque mouvement de la souris

    Entre temps, j'ai trouvé une autre solution pour ancrer le canvas de la SB. Comme il semble qu'il ne soit ancré que lors du premier événement le concernant, dans le FormCreate de la fiche, j'ai juste ajouté un SB.Canvas.MoveTo(0,0) et il n'y a plus de décalage entre les coordonnées et la position du point tracé.

    André

  16. #16
    Membre expert
    Citation Envoyé par alanglet Voir le message
    Bonjour,
    Exact et ce serait plus simple les coordonnées de la souris sur l'image retournées par les événements OnMouse n'ayant pas à être transformées. Mais il faudrait alors gérer aussi l'effacement du trait précédent sur l'image à chaque mouvement de la souris
    Non pas besoin, car tu dessines sur le canvas du contrôle et non sur le bitmap directement

    Citation Envoyé par alanglet Voir le message

    Entre temps, j'ai trouvé une autre solution pour ancrer le canvas de la SB. Comme il semble qu'il ne soit ancré que lors du premier événement le concernant, dans le FormCreate de la fiche, j'ai juste ajouté un SB.Canvas.MoveTo(0,0) et il n'y a plus de décalage entre les coordonnées et la position du point tracé.

    André
    Bizarre ce truc, et en mettant le TImage à alTop, ou alLeft ?

    A+
    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  17. #17
    Membre expert
    Ci-joint une petite app de test sur l'allocation de la mémoire avec le gestionnaire de tâche ouvert pour observer le comportement.

    Cela permettra peut-être d'y voir plus clair sur les limitations.

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  18. #18
    Membre expert
    Une petite question que j'ai oublié de te demander : (plusieurs petites, en fait )
    Citation Envoyé par alanglet Voir le message

    Cette application est développée en 32b simplement pour des raisons de compatibilité avec une autre application dont elle est une sorte de "périphérique".
    Pourrais tu nous en dire plus, c'est dans quel but ? une sorte de "périphérique" ? comment tu dialogues entre les 2 ? ton app est elle vraiment obligée d'être en 32 bits pour dialoguer avec ton périphérique "virtuel", c'est une DLL ?

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  19. #19
    Membre averti
    Citation Envoyé par BeanzMaster Voir le message
    Non pas besoin, car tu dessines sur le canvas du contrôle et non sur le bitmap directement
    Bizarre ce truc, et en mettant le TImage à alTop, ou alLeft ?
    Dessiner sur Image.Canvas a le même effet que dessiner sur son bitmap. Il n'y a pas d'effacement lors du déplacement dans la SB. De plus il y a un autre inconvénient: à l'extrémité du trait doit s'afficher un texte avec DrawText(). Il ne s'affiche pas, est-ce parce que un TImage n'a pas de propriété Font?
    Le TImage est dans le TScrollBox AlNone Left=0 et Top=0, et le simple SB.Canvas.MoveTo(0,0) qui suffit pour ancrer le Canvas de la ScrollBox est exécuté dans le FormCreate avant de charger une image. Sans le MoveTo, quelque soit l'alignement (j'ai essayé), l'ancrage du Canvas dans sa SB ne se fait que lors de son activation par une instruction du type MoveTo, Line etc...

    André

  20. #20
    Membre averti
    Bonsoir BeanzMaster,

    L'erreur Out of Memory intervient lors du getmem de l'allocation du 3ième buffer de 512 Mo.
    Pour mémoire, en 32b la variable de boucle for i:=.. ne peut pas être un Int64...

    André