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

Lazarus Pascal Discussion :

Taille maximale d'une image


Sujet :

Lazarus Pascal

  1. #21
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Que ce soit signé ou pas c'est la même chose lorsque c'est négatif cela signifie que l'image est codée de bas en haut ou de droite à gauche.
    J'ai barré un bout parce qu'à te lire on pourrait croire que le sens de lecture des pixels de la ligne pourrait être inversé, chose que je n'ai jamais rencontrée tout au long de mes lectures du web.
    Alors que l'inversion du sens de parcours de la hauteur est bien connue.

    Citation Envoyé par BeanzMaster Voir le message
    C'est pas le BMP en lui-même, ce sont les fonctions de Lazarus/FPC qui posent problèmes
    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

  2. #22
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    J'ai barré un bout parce qu'à te lire on pourrait croire que le sens de lecture des pixels de la ligne pourrait être inversé, chose que je n'ai jamais rencontrée tout au long de mes lectures du web.
    Alors que l'inversion du sens de parcours de la hauteur est bien connue.
    Oui t'as raison, moi aussi jamais vue de ligne inversée sauf dans le format TGA. Mais ça c'est indiqué par un paramètre de l'en-tête.
    Le "de droite à gauche c'était c'était juste pour précisé au cas ou
    • "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

  3. #23
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 671
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 671
    Points : 13 065
    Points
    13 065
    Par défaut
    Scanline nous renvoie un pointeur permettant de lire les pixels du bitmap d'une seule traite parce que c'est un seul bloc mémoire.
    Théoriquement, l'image est limitée par la taille mémoire allouée au processus mais pratiquement, c'est maximum la plus grande zone de mémoire contiguë en tenant compte de sa fragmentation.

  4. #24
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Salut,
    Citation Envoyé par Andnotor Voir le message
    Théoriquement, l'image est limitée par la taille mémoire allouée au processus
    moi, ça je le comprends comme ça :
    l'image qui peut être affichée (= présentée à l'utilisateur) est limitée par la taille mémoire allouée au processus, indépendamment de la taille du fichier qui contient les données (et qui peut être gigantesque), si tant est qu'on veuille essayer de tout faire afficher d'un coup, ce qui imposerait un écran d'une taille démente et qui n'existe pas actuellement.
    Le problème est donc contourné par les logiciels d'affichage qui ne vont piocher qu'une partie du fichier pour la présenter dans la zone définie par l'utilisateur, ou vont utiliser un rapport de zoom en fonction de la taille disponible pour l'affichage, ce qu'a fait mon Gimp hier soir qui m'a ouvert mon fichier de 400 Mo en une poignée de secondes et un zoom à 9% environ (de mémoire) alors que le TImage.Picture.LoadFromFile m'a mis la machine presque à genoux...

    Andnotor a un esprit de synthèse, de raccourci et de concision qui fait sauter tous les détails et oblige à une réflexion en profondeur (ce qui n'est pas plus mal, notez bien),


    Citation Envoyé par der§en Voir le message
    Côté sauvegarde, c'est bizarre que le bmp pose problème, il me semblait que c'était le format natif de Windows,
    Trouvé dans mes lectures sur le web que le bmp a été inventé avant Windows, à une époque où les disques durs n'offraient que quelques 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

  5. #25
    Membre du Club

    Profil pro
    Inscrit en
    Juin 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 15
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Ca c'est juste si le BMP en codé en version 1 ('l'en-tête de la Version 5 = 124 octets). Ce que tu décrit n'est pas une généralité.
    -> ce que je décris est général pour les Bitmap générés par TBitmap sous Lazarus 1.6 / ubuntu 16.04 x64
    -> Il respectent tous la règle de l'entete 54 octets
    -> TailleFichier = w x h x (pfxxbit / 8) + 54 ; par encore constaté de cas v5 à 124 octet d'entete sur les bmp que je génère.
    -> Ex : Pas vu de fichier bmp 8x8 pf24b obtenu après un bmp.save('toto.bmp') qui ne ferait pas 246 octets = 8x8x3 + 54 octets
    -> Peut-être encore vrai pour les autres bib comme BGRABitmap.



    Citation Envoyé par BeanzMaster Voir le message
    Faux la taille n'est pas obligatoirement de 4, rien à voir C'est la LIGNE CODEE dans le fichier BMP qui doit être alignée sur 32bits
    -> ce que je veux dire c'est que la formule w x h x pfxxb/8 ne se vérifie plus forcément en cas de dimension non multiple de 4, à cause justement du complément que tu évoques. C'est à prendre en compte si on veux calculer le plus gros bmp générable possible en v1.


    Citation Envoyé par BeanzMaster Voir le message
    Que se soit signé ou pas c'est la même chose lorsque c'est négatif cela signifie que l'image est codée de bas en haut ou de droite à gauche
    Les calculs de taille se font toujours sur les valeurs absolues.
    -> sauf que la valeur absolue signée ne dépasse pas 2 Milliards, 4 Milliards en non signé
    -> on aurait pu doubler la taille des fichiers pour fleurter avec les 4 Milliards d'octets, 4Go gérés au lieu de 2Go.
    -> donc quasi doubler sur une des dimensions des plus grands bitmap trouvés (Exploser le 32000 x 16000 pour faire du 32000 x 32000 x 4 = env 4Go ! )
    -> et quand on se permet de doubler un record, il reste habituellement peu de gens pour dire que ça ne change rien.

    ludo

  6. #26
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Ludelphi7 Voir le message
    -> ce que je décris est général pour les Bitmap générés par TBitmap sous Lazarus 1.6 / ubuntu 16.04 x64
    -> Il respectent tous la règle de l'entete 54 octets
    -> TailleFichier = w x h x (pfxxbit / 8) + 54 ; par encore constaté de cas v5 à 124 octet d'entete sur les bmp que je génère.
    -> Ex : Pas vu de fichier bmp 8x8 pf24b obtenu après un bmp.save('toto.bmp') qui ne ferait pas 246 octets = 8x8x3 + 54 octets
    -> Peut-être encore vrai pour les autres bib comme BGRABitmap.
    C'est vrai Lazarus génère que des BMP v1
    Idem pour BGRABitmap la description du format ne change pas. BGRABitmap se base sur TFPCustomImage

    Citation Envoyé par Ludelphi7 Voir le message
    -> ce que je veux dire c'est que la formule w x h x pfxxb/8 ne se vérifie plus forcément en cas de dimension non multiple de 4, à cause justement du complément que tu évoques. C'est à prendre en compte si on veux calculer le plus gros bmp générable possible en v1.
    Tu te mélange les pinceaux avec ce padding comme moi au début. Jette un oeil à cette discussion On en a vu de toute les couleurs. Regardes la formule d'AndNotOr Cette histoire de padding entre autre nous en a fait baver un peu

    Citation Envoyé par Ludelphi7 Voir le message
    -> sauf que la valeur absolue signée ne dépasse pas 2 Milliards, 4 Milliards en non signé
    -> on aurait pu doubler la taille des fichiers pour fleurter avec les 4 Milliards d'octets, 4Go gérés au lieu de 2Go.
    -> donc quasi doubler sur une des dimensions des plus grands bitmap trouvés (Exploser le 32000 x 16000 pour faire du 32000 x 32000 x 4 = env 4Go ! )
    -> et quand on se permet de doubler un record, il reste habituellement peu de gens pour dire que ça ne change rien.

    ludo[/QUOTE]

    Comme la si bien dit AndNotOr c'est la quantité de mémoire dispo qui determine la taille maximale.
    J'ai fais des tests avec mon projet, j'ai créé sans soucis un bitmap de 32000x32000 et ce en quelques secondes, comparé aux minutes du TBitmap.

    Pour ce qui est de l'écran noir à l'enregistrement du fichier BMP j'ai regardé Ici
    Voila le code :
    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Bmp: TBitmap;
    begin
      Bmp := TBitmap.Create;
      Bmp.PixelFormat := pf32bit;
      Bmp.Width := 32768;
      Bmp.Height := 16384;
      Bmp.Canvas.Pen.Color := clYellow;
      Bmp.Canvas.Brush.Color := clYellow;
      Bmp.Canvas.Lock; // --> J'ai lu ça aussi quelque part mais pas sur qu'il y ai un rapport
      Bmp.Canvas.Rectangle(0, 0, 32768, 16384);
      Bmp.Canvas.UnLock;
      Bmp.Canvas.Changed; //-->Pour que l'enregistrement soit ok 
     
      Bmp.SaveToFile('test.bmp');
      Bmp.Free;
     
      Image1.Picture.LoadFromFile('test.bmp');
    end;
    Avec une taille de 16000x8000 ok le fichier est bien enregistré = 512Mo
    Avec une taille de 32000x16000 ok le fichier est bien enregistré = 2GO
    Avec une taille de 32768x16384 paf fichier noir
    Avec une taille de 32767x16383 ok le fichier est bien enregistré, y'a un beau pavé bien jaune, et il est bien de la bonne taille

    Il semblerait bien que le mécanisme du TBitmap lors de l'enregistrement d'un tel fichier soit limitée. Mais au vu de la consommation mémoire du TBitmap, ça m'étonne qu'à moitié.
    La taille maximale qu'un TBitmap peux enregistrer sous Lazarus 1.6.4 64bits et sous windows 10 est de 32767x16383

    A+
    • "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

  7. #27
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Comme l'a si bien dit AndNotOr c'est la quantité de mémoire dispo qui détermine la taille maximale.
    Je ne suis pas d'accord, je l'ai écrit ce matin, et je continue à trouver ça insensé ! Que l'affichage soit soumis à des conditions de disponibilité de mémoire, d'accord, mais pas l'enregistrement du fichier, qui peut très bien être effectué à coups de BlockWrite consécutifs.

    Citation Envoyé par BeanzMaster Voir le message
    La taille maximale qu'un TBitmap peut enregistrer sous Lazarus 1.6.4 64bits et sous windows 10 est de 32767x16383
    Quant à la taille maximale, je viens de tester sous un vieux XP avec Laz 32 bits 1.6rc1, si je tente 16383x8191 c'est run error 203, et si je descends à 12287x8191 ça génère un fichier pf32bit de 402 Mo.
    Flemme de chercher où ça coince entre 12287 et 16383.


    J'ai un outil qui mesure l'occupation mémoire. Quand la machine virtuelle XP ne fait rien, elle a 880 Mo libres et pour générer ce fichier de 402 Mo j'ai eu des chutes à 1,5 Mo libre seulement : le prog consommait beaucoup plus que le fichier, alors savoir comment c'est calculé, là je passe la main.
    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

  8. #28
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Je ne suis pas d'accord, je l'ai écrit ce matin, et je continue à trouver ça insensé ! Que l'affichage soit soumis à des conditions de disponibilité de mémoire, d'accord, mais pas l'enregistrement du fichier, qui peut très bien être effectué à coups de BlockWrite consécutifs.
    Ce n'est pas l'affichage qui est soumis à ces conditions. La taille de ton écran reste la même. De nos jours nos machines disposent de quantité de RAM importante (j'ai 16GO j'ai de quoi faire) donc "Théoriquement" je devrai pouvoir créer une image de 16Go en "Mémoire". Pour l'affichage de très très très grosse image il faudrait utiliser un système semblable au "File Mapping", (je le vois comme ça) Tu utilise une fenêtre au dimension de ton écran pour lire les données en fonction de sa position. Pour l'enregistrement c'est la même chose mais pour des fichiers plus gros que la RAM il faudrait mettre en place un système avec un vrai "File Mapping" mais "inverser" cette fois. Ce qui signifiai un bloque mémoire "mapper" sur le disque dur, afin de compenser les 8 Go de ram qui manque (et oui l'image que je veux créer fait 24Go et je n'ai que 16Go de RAM) et ceci dans les 2 sens lecture/écriture (j'en mal au crane juste d'essayer de penser, a comment mettre un telle système en place. Pour la lecture encore ça va, mais pour la création et l'écriture c'est une autre histoire)
    Créer une image de 24go n'est pas compliquer en soit si on la génère sur un support physique, (a juste titre à grand coup de blockwrite, comme tu le dis) mais là encore il y a une limite. Et les données de base de ton immense image, tu les stockes ou ?

    Citation Envoyé par Jipété Voir le message
    Quant à la taille maximale, je viens de tester sous un vieux XP avec Laz 32 bits 1.6rc1, si je tente 16383x8191 c'est run error 203, et si je descends à 12287x8191 ça génère un fichier pf32bit de 402 Mo.
    Flemme de chercher où ça coince entre 12287 et 16383.

    J'ai un outil qui mesure l'occupation mémoire. Quand la machine virtuelle XP ne fait rien, elle a 880 Mo libres et pour générer ce fichier de 402 Mo j'ai eu des chutes à 1,5 Mo libre seulement : le prog consommait beaucoup plus que le fichier, alors savoir comment c'est calculé, là je passe la main.
    880 Mo Libre, Image 402 Mo une difference de 400 Mo. Windows ne réserverai(garderai)-t-il pas ces "400" mo justement pour les autres processus ? Quelles sont les limites imposées par les OS (Win et Linux) idem ? différent ?

    Avant il y avait les fonctions MaxAvail et MemAvail. Elle étaient pratique pour pas dépasser. Maintenant existe il une solution multiOS (Win/Nux) quelques part dans les recoins de fpc ou lazarus ?
    • "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

  9. #29
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 754
    Points : 943
    Points
    943
    Par défaut
    C'est le Tbitmap qui bloque à 32767 x 16383 ou c'est la routine de sauvegarde en BMP ?

    Si c'est la routine, un PNG me convient tout autant !

    @BeanzMaster, il n'est pas impossible dans une future proche ou l'on me demandera une taille encore plus grande, du coup, je suis vraiment intéressé par la solution que tu as trouvé, pourrais-tu m'en dire plus ?

  10. #30
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par der§en Voir le message
    C'est le Tbitmap qui bloque à 32767 x 16383 ou c'est la routine de sauvegarde en BMP ?
    C'est la routine qui coince, puisque mon tout premier test a été fait avec des integer signés, donc 231 utiles.


    Citation Envoyé par BeanzMaster Voir le message
    Ce n'est pas l'affichage qui est soumis à ces conditions
    Alors c'est dramatique...

    Citation Envoyé par BeanzMaster Voir le message
    Et les données de base de ton immense image, tu les stockes où ?
    Ben sur le disque, pourquoi ?
    Il faut considérer une grande image comme un assemblage de petites images, exactement comme une (petite) image normale est un assemblage de pixels (qui ne sont rien d'autre que des assemblages de bits).
    Je ne vois pas où est le problème, après tout, il y a des gens qui travaillent sur les très grands nombres, qui sont des constructions artificielles qui n'existent pas en réalité puisque dépassant largement les capacités physiques du processeur.

    Citation Envoyé par BeanzMaster Voir le message
    880 Mo Libre, Image 402 Mo une difference de 400 Mo. Windows ne réserverai(garderai)-t-il pas ces 400 Mo justement pour les autres processus ?
    Non, puisque comme je l'ai écrit, l'espace libre tombait par moments à seulement 1,5 Mo pendant la phase de génération du fichier.

    Citation Envoyé par BeanzMaster Voir le message
    Avant il y avait les fonctions MaxAvail et MemAvail. Elle étaient pratiques pour pas dépasser. Maintenant existe-t-il une solution multiOS (Win/Nux) quelque part dans les recoins de fpc ou lazarus ?
    Je ne sais pas ; sous Linux je vais lire /proc/meminfo que je parse ensuite (on y trouve du MemTotal et du MemFree entre autres).
    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

  11. #31
    Membre du Club

    Profil pro
    Inscrit en
    Juin 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 15
    Points : 53
    Points
    53
    Par défaut
    Je vais être plus explicite.
    La routine d'écriture et d'autres mécanismes internes utilise un compteur interne 4octets signé, calculé et écrit dans le 2nd champ d'entete du fichier.
    Ce compteur déconne grave dès que la taille fichier dépasse 2Go.
    Au delà de 2Go, cette valeur devient forcément erronée (en v1) et cette routine déclenchera forcément tôt ou tard un débordement mémoire (Mais je ne remets pas en cause qu'elle peut planter avant).
    Idem pour l'éventuel routine de lecture, Lazarus ou d'un programme tiers, qui lira une valeur erronée avec les même conséquences de plantage si la valeur TailleFichier ou TailleData (7eme champ) indiquée en entête fichier afin de prévoir les réservations mémoire sont "grave fausse" à cause d'un débordement de votre entier signé.
    Concernant TailleFichier, cette valeur devient archi-fausse à cause des 54 octets de l’entête pour une taille bmp 32768x16384x4, (maudit entête !).
    Elle redevient valide pour 32768x16383x4 -> TailleFichier = 2^31-32768+54 < 2Go
    Je persiste à penser que la lecture et l'écriture de grands bitmaps (v1) est impossible au delà de TailleFichier = 2Go, même avec un Lazarus ou un programe tiers qui seraient parfaitement dénués de bugs, du moins tant qu'ils feront confiance à ce champ/compteur et son copain TailleData pour la réservation mémoire.
    C'est ce qu'on appelle une limite théorique, codée en dur dans les champs qui servent au calcul de la réservation mémoire du logiciel qui va lire le bmp.
    Cette limite théorique vient du format de fichier, pas de Linux/Lazarus.
    Le codage de TailleFichier en non signé reculerait cette limite au double de pixels.
    Ceci dit, je ne puis affirmer que Linux/Lazarus saurait gérer sans bug cette autre limite théorique.
    ludo

  12. #32
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Ludelphi7 Voir le message
    Je vais être plus explicite.
    La routine d'écriture et d'autres mécanismes internes utilise un compteur interne 4octets signé, calculé et écrit dans le 2nd champ d'entete du fichier.
    Ce compteur déconne grave dès que la taille fichier dépasse 2Go.
    Au delà de 2Go, cette valeur devient forcément erronée (en v1) et cette routine déclenchera forcément tôt ou tard un débordement mémoire (Mais je ne remets pas en cause qu'elle peut planter avant).
    Idem pour l'éventuel routine de lecture, Lazarus ou d'un programme tiers, qui lira une valeur erronée avec les même conséquences de plantage si la valeur TailleFichier ou TailleData (7eme champ) indiquée en entête fichier afin de prévoir les réservations mémoire sont "grave fausse" à cause d'un débordement de votre entier signé.
    Heu ben non c'est pas obligatoire dans ma solution je tiens pas du tout compte de ces 2 variables pour lire les fichiers BMP et je prend en charge 99% du format BMP de la V1 à la V5 en passant par les type Os/x

    Citation Envoyé par Ludelphi7 Voir le message
    Concernant TailleFichier, cette valeur devient archi-fausse à cause des 54 octets de l’entête pour une taille bmp 32768x16384x4, (maudit entête !).
    Elle redevient valide pour 32768x16383x4 -> TailleFichier = 2^31-32768+54 < 2Go
    Je persiste à penser que la lecture et l'écriture de grands bitmaps (v1) est impossible au delà de TailleFichier = 2Go, même avec un Lazarus ou un programe tiers qui seraient parfaitement dénués de bugs, du moins tant qu'ils feront confiance à ce champ/compteur et son copain TailleData pour la réservation mémoire.
    Le problème n'est pas la quantité que l'on écrit sur le Disque sur veux ecrire un fichier de 15go rien ne t'en empêche. Mais l'allocation en mémoire RAM

    Citation Envoyé par Ludelphi7 Voir le message
    C'est ce qu'on appelle une limite théorique, codée en dur dans les champs qui servent au calcul de la réservation mémoire du logiciel qui va lire le bmp.
    Si ell est codée en dur, elle n'est pas théorique

    Citation Envoyé par Ludelphi7 Voir le message
    Cette limite théorique vient du format de fichier, pas de Linux/Lazarus.
    Le codage de TailleFichier en non signé reculerait cette limite au double de pixels.
    Ceci dit, je ne puis affirmer que Linux/Lazarus saurait gérer sans bug cette autre limite théorique.
    ludo
    Nom ce n'est pas le format BMP, en cause mais belle et bien la gestion des Bitmaps dans Lazarus
    J'ai bien pu créer une image de 32000x32000 soit environ 4Go et pas de soucis. le maximum d'une dimension est la valeur maximal de l'entier signé et comme je le disait vu que lorsque l'on crée un image c'est en RAM et non sur HD. C'est limité en fonction de la mémoire disponible. Après cela dépend aussi de l'architecture 32bits ou 64bits et de la façon dont les OS gère la mémoire entre les différents processus.

    Citation Envoyé par der§en Voir le message
    C'est le Tbitmap qui bloque à 32767 x 16383 ou c'est la routine de sauvegarde en BMP ?
    Si c'est la routine, un PNG me convient tout autant !
    A mon avis c'est la routine de sauvegarde qui est limité. Seulement celle du BMP ? je pense que le problème persistera avec le PNG, ayant pas mal décrypter les codes concernant la gestion des bitmap avec Lazarus/FPC.
    Il semble vraiment avoir un problème du coté de la gestion de la mémoire.
    Je viens de tester ce bout de code

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    unit uimagesize1;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
      ExtCtrls,
      GraphType, IntfGraphics, fpimage, fpreadpng,fpwritepng;
     
    type
     
      { TForm1 }
     
      TForm1 = class(TForm)
        Button1: TButton;
        Image1: TImage;
        procedure Button1Click(Sender: TObject);
      private
     
      public
     
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.lfm}
     
    { TForm1 }
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Bmp: TBitmap;
      I, J, W, H: Integer;
      lzimg: TLazIntfImage;
      Png: TPortableNetworkGraphic;
    begin
      W := 32767;
      H := 16383;
     
      Bmp := TBitmap.Create;
      try
        Bmp.PixelFormat := pf32bit;
        Bmp.Width := W;
        Bmp.Height := H;
        Bmp.Canvas.Pen.Color := clYellow;
        Bmp.Canvas.Brush.Color := clYellow;
        BMP.Canvas.Lock;
        Bmp.Canvas.Rectangle(100, 100, W-100, H-100);
        bmp.Canvas.Unlock;
        Bmp.Canvas.Changed;
     
        { Png := TPortableNetworkGraphic.Create  Obligatoire pour la prise en charge de la transparence.
          TTLazIntfImage.Savetofile('test.png'); ne sauvegarde pas la transparence
        }
        Png := TPortableNetworkGraphic.Create;
        try
          lzimg := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);
          try
            lzimg.SetSize(W, H);
            lzimg.LoadFromBitmap(Bmp.Handle,bmp.MaskHandle,W,H);
            Bmp.free;
            Png.LoadFromIntfImage(lzimg);
          finally
            lzimg.Free;
          end;
          Png.SaveToFile('test.png');
        finally
          Png.Free;
        end;
      finally
        Image1.Picture.LoadFromFile('test.png');
      end;
     
    end;
     
    end.
    Résultat aucun problème le fichier est parfait écrit et lu
    Avec
    W := 32768;
    H := 16384;

    Paf
    Nom : 2017-08-11_153241.jpg
Affichages : 283
Taille : 26,1 Ko

    Voici donc les fameuses limites théorique codées en dur de Ludelphi7
    Qui nous renvoi vers cette fonction dont le code se trouve je ne sais ou et pas envie de me prendre la tête à chercher

    Citation Envoyé par der§en Voir le message
    il n'est pas impossible dans une future proche ou l'on me demandera une taille encore plus grande, du coup, je suis vraiment intéressé par la solution que tu as trouvé, pourrais-tu m'en dire plus ?
    Oui bien sure. Petite histoire.
    Comme certain le savent et ont pu le lire, je fais parti de la communauté de GLScene, dont je suis le "modérateur actuel" pour Lazarus. J'ai récemment mis à jour cette librairie pour Lazarus et je continue à faire quelques modifs entre 2.
    Il y a un réel problème avec FPC/Lazarus avec la gestion des bitmaps. Elle est fonctionnelle pour des choses vraiment très très basique (ou sinon il faut directement passé par FPImage c'est le plus simple à mon avis).
    Ici sur ce forum nous avons eu quelques discussions à ce sujet (cf celle cité ici dans ce fil). Mais surtout il y a eu celle-ci qui m'a donné envie d'essayer de coder "mon projet" (cela faisait seulement quelques moi que je m'étais remis à programmer). Ensuite GLscene, j'ai été frustré de ne pas pouvoir utilisé cette librairie avec Lazarus. Il y a bien CodeTyphon mais le code n'est pas du tout à jour. De plus GLScene se faisant vieillissant, il ne gère que partiellement et vraiment pas correctement l' "OpenGL Core" (v3.3 et sup). De plus au fil des années et des contributions le code c'est largement alourdi et il y pas mal de fonctions dupliquées ce qui a du coup un impact sur les performances dans bon nombre de cas.
    Après, la librairie GraphicEx à été codé par Mike Lischke qui est également l'auteur originel de GLScene. Du coup je me suis dis faisons d'une pierre deux coup. Et voila, maintenant qu'un nouveau projet est né "GLZScene". J'ai donc repris la base de GLScene, je l'ai modifié, amélioré, ajoutés pas mal de classes, j'ai retranscrit les commentaires anglais vers le français du mieux que je pouvais,...
    Et j'ai donc naturellement ajouter une gestion des bitmaps indépendante et optimisée, avec une gestion des fichiers très similaires à GraphicEx et je peux maintenant aisément ajouter le support des différents formats de fichiers.
    Je me suis amusé aussi à faire des recherches et ai rajouté l'essentiel pour pouvoir réaliser du traitement d'image en autres choses. Il y a également un "Canvas" pour dessiner. Voila maintenant je voudrais terminer ou du moins mettre en place deux choses fonctionnelles : L'écriture de texte via FreeType et la gestion des masques pour appliquer la transparences, les effets et tout ce qui en découle. J'aimerai également inclure le support en lecture et écriture des formats JPEG et PNG. Et fini l'écriture des formats BMP, TGA, XPM, PNM. Un fois là je publierai les sources de la 1ere "pre"-version.
    Coté 3D j'ai déja une partie de faite, me restera plus qu'a raccordé tout çà.

    J'en profite du coup, si jamais le projet vous intéresse et que vous souhaitez y participer n'hésitez pas, contactez moi !

    A+
    • "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

  13. #33
    Membre du Club

    Profil pro
    Inscrit en
    Juin 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 15
    Points : 53
    Points
    53
    Par défaut
    Si tu crées un bmp 32000*32000*4 en v1 (4Go sur disque), ton champ entete de fichier n'indiquera pas la bonne taille = 4 096 000 054 mais une taille erronée = -198 967 242.
    Idem pour le champ TailleData qui sera tout aussi faux.
    Que tu trouves des astuces pour lire et écrire de tels fichiers n'empèche pas le fait que tu crées des fichiers qui ne sont plus valides, qui comportent de fausses indications sur les tailles déclarées.
    Prévenir les autres programmeurs revient à créer un nouveau format maison "v1plus" ou "BMP_BeanMaster" dans lequel on se met d'accord qu'il ne faut plus tenir compte de ces champs non valides, mais faire à la place faire une routine genre TailleData=TailleOcupée sur disque (int64) -54.
    Ne pas prévenir revient à lâcher dans la nature des fichiers qui risquent de faire bugger toutes les applis qui se fient à l'intégrité des fichiers lus, applis garanties uniquement sur les fichiers qui respectent le format.
    Respecter un format ne se limite pas à écrire au bon endroit, mais aussi y écrire des valeures exactes exemptes de toute fausse indication.

    ludo

  14. #34
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Je viens de tester ce bout de code
    [--snip--]
    Résultat aucun problème le fichier est parfait écrit et lu
    T'en as d'la chance !

    Je copie/colle ton code dans un projet de test basé sur TLazIntfImage (comme ça les uses sont bons), je rajoute un bouton, je n'ai rien changé à ton bout de code à part le chemin d'enregistrement du fichier, j'exécute avec 32767 et 16383 et tu sais quoi ?
    Paf !
    Nom : sigfpe.png
Affichages : 624
Taille : 15,0 Ko

    Y a vraiment de quoi se l'attraper et se la mordre ! Ou tu ne nous as pas tout dit et il manque un bout quelque part ?
    En pas-à-pas c'est cette ligne qui fait planter : lzimg.LoadFromBitmap(Bmp.Handle,bmp.MaskHandle,W,H);...

    Ce qui est intéressant, c'est le commentaire lié à l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    {------------------------------------------------------------------------------
      procedure RaiseGDBException(const Msg: string);
     
      Raises an exception.
      Normally gdb does not catch fpc Exception objects, therefore this procedure
      raises a standard "division by zero" exception which is catched by gdb.
      This allows one to stop a program, without extra gdb configuration.
     ------------------------------------------------------------------------------}
    En gros l'erreur n'est pas une division par zéro, mais les programmeurs ont mis ça là pour arrêter le prog pour qu'on puisse aller trifouiller, mais où ? Nobody knows...

    Ah, pendant que j'y suis (dans le code), si l'on joue avec TLazIntfImage, je ne vois pas pourquoi on se limiterait à 32767 x 16383 puisque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TLazIntfImage.SetSize(AWidth, AHeight: integer);
    begin
      InternalSetSize(AWidth, AHeight);
      CreateData;
    end;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure TLazIntfImage.InternalSetSize(AWidth, AHeight: integer);
      procedure Error;
      begin
        raise FPImageException.Create('Invalid Size');
      end;
    begin
      if (AWidth = Width) and (AHeight = Height) then exit;
      if (AWidth<0) or (AHeight<0) then Error;
      inherited SetSize(AWidth, AHeight);
     
      FRawImage.Description.Width := Width;
      FRawImage.Description.Height := Height;
    end;
    Vous voyez des limitations, des alertes, des warnings, quelque chose pour nous prévenir que des valeurs démentes (mais dans la limite de 231-1 quand même) vont tout faire foirer ? Moi non je ne vois rien...
    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

  15. #35
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Ludelphi7 Voir le message
    Si tu crées un bmp 32000*32000*4 en v1 (4Go sur disque), ton champ entete de fichier n'indiquera pas la bonne taille = 4 096 000 054 mais une taille erronée = -198 967 242.
    Idem pour le champ TailleData qui sera tout aussi faux.
    Je suis d'accord avec ça l'en-tête du fichier BMP sera invalide, je n'ai pas jamais dis le contraire. Mais si ce paramètre est incorrecte tu pourras lire ton fichier quand même. Je te laisse jeter un oeil dans Lcl\IntfGraphics.pas et tu verras que même Lazarus n'utilises pas ces paramètres pour lire les fichiers BMP.

    Citation Envoyé par Ludelphi7 Voir le message
    Que tu trouves des astuces pour lire et écrire de tels fichiers n'empèche pas le fait que tu crées des fichiers qui ne sont plus valides, qui comportent de fausses indications sur les tailles déclarées.
    Prévenir les autres programmeurs revient à créer un nouveau format maison "v1plus" ou "BMP_BeanMaster" dans lequel on se met d'accord qu'il ne faut plus tenir compte de ces champs non valides, mais faire à la place faire une routine genre TailleData=TailleOcupée sur disque (int64) -54.
    Ne pas prévenir revient à lâcher dans la nature des fichiers qui risquent de faire bugger toutes les applis qui se fient à l'intégrité des fichiers lus, applis garanties uniquement sur les fichiers qui respectent le format.
    Respecter un format ne se limite pas à écrire au bon endroit, mais aussi y écrire des valeures exactes exemptes de toute fausse indication.
    ludo
    Trouver des astuces ? Non ! Par contre, j'ai fait énormément de recherches et j'ai suivi bon nombres de recommandations sur ce format. J'ai analysé des dizaines de sources différentes (en C, Python, pascal). J'ai passé plus d'1 mois et demi pour arriver à prendre en charge le format BMP correctement à 99%. Car mine de rien ce format n'est pas aussi simple qu'il te parait.

    Regardes donc du coté de http://entropymine.com/jason/bmpsuite/ Il y quelques fichiers BMP dont les en-têtes sont invalides (dossier X) et tu te rendra comptes que bon nombres de visualiseurs, liront, mais n'afficheront pas correctement ces fichiers (tu peux verifier il y a un dossier avec une page HTML et des fichiers en JPG servant de références).
    Leurs en-têtes sont invalide mais pas impossible à lire.

    Créer un nouveau format pourquoi faire ? peut-être un jour si le besoin s'en ressent.
    Et suis d'accord avec toi il faut mieux prévenir que guérir
    Respecter un format ne se limite pas à écrire au bon endroit, mais aussi y écrire des valeurs exactes exemptes de toute fausse indication.
    . Mais malheureusement il y a beaucoup de cas, ou ce n'est pas vrai et certains logiciels ne respectent pas tes dires, malheureusement.

    Citation Envoyé par Jipété Voir le message
    T'en as d'la chance !

    Je copie/colle ton code dans un projet de test basé sur TLazIntfImage (comme ça les uses sont bons), je rajoute un bouton, je n'ai rien changé à ton bout de code à part le chemin d'enregistrement du fichier, j'exécute avec 32767 et 16383 et tu sais quoi ?
    Paf !

    Y a vraiment de quoi se l'attraper et se la mordre ! Ou tu ne nous as pas tout dit et il manque un bout quelque part ?
    En pas-à-pas c'est cette ligne qui fait planter : lzimg.LoadFromBitmap(Bmp.Handle,bmp.MaskHandle,W,H);...
    Serait-ce parce que tu est en 32bits ? Serait-ce Lazarus 1.4 ?
    et Idem chez moi c'est cette ligne qui fait planter

    Citation Envoyé par Jipété Voir le message

    Ce qui est intéressant, c'est le commentaire lié à l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    {------------------------------------------------------------------------------
      procedure RaiseGDBException(const Msg: string);
     
      Raises an exception.
      Normally gdb does not catch fpc Exception objects, therefore this procedure
      raises a standard "division by zero" exception which is catched by gdb.
      This allows one to stop a program, without extra gdb configuration.
     ------------------------------------------------------------------------------}
    En gros l'erreur n'est pas une division par zéro, mais les programmeurs ont mis ça là pour arrêter le prog pour qu'on puisse aller trifouiller, mais où ? Nobody knows...
    Encore un truc non finalisé
    Mais bizarre ton erreur on dirait un exception sur le message de l'exception de l'erreur (tordu ce truc)

    Citation Envoyé par Jipété Voir le message
    Ah, pendant que j'y suis (dans le code), si l'on joue avec TLazIntfImage, je ne vois pas pourquoi on se limiterait à 32767 x 16383 puisque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TLazIntfImage.SetSize(AWidth, AHeight: integer);
    begin
      InternalSetSize(AWidth, AHeight);
      CreateData;
    end;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure TLazIntfImage.InternalSetSize(AWidth, AHeight: integer);
      procedure Error;
      begin
        raise FPImageException.Create('Invalid Size');
      end;
    begin
      if (AWidth = Width) and (AHeight = Height) then exit;
      if (AWidth<0) or (AHeight<0) then Error;
      inherited SetSize(AWidth, AHeight);
     
      FRawImage.Description.Width := Width;
      FRawImage.Description.Height := Height;
    end;
    Vous voyez des limitations, des alertes, des warnings, quelque chose pour nous prévenir que des valeurs démentes (mais dans la limite de 231-1 quand même) vont tout faire foirer ? Moi non je ne vois rien...
    de même que inherited SetSize (TFPCustomImage). Par contre dans CreateData tu as jeté un oeil au cas ou ?

    Le problème semble être est ailleurs et ça se passe au niveau des allocations mémoires..
    Quand tu vois que charger un fichier de 2Go avec juste un TImage et un TButton, et que l'utilisation en mémoire est plus du double, c'est qu'il y a un soucis déja à ce niveau.
    Maintenant trouver ou est le problème dans ce sac de nœuds entre la LCL et la FCL piouf. Pour ma part je n'ai pas assez de temps à y consacrer.
    • "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

  16. #36
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Serait-ce parce que tu es en 32bits ? Serait-ce Lazarus 1.4 ?
    et Idem chez moi c'est cette ligne qui fait planter
    Oui je suis en 32 bits et oui, c'est toujours la 1.4, mais ce que je ne capte pas du tout c'est que tu dis ce soir que chez moi c'est cette ligne qui fait planter alors que cet après-midi tu disais que ça fonctionnait bien. C'est quoi ce délire ?


    Bref, je viens de m'amuser à creuser ce crash :
    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
    // Analyse pas-à-pas de la ligne lzimg.LoadFromBitmap(Bmp.Handle,Bmp.MaskHandle,W,H);
     
    // On commence par entrer dans 
    function TCustomBitmap.GetMaskHandle: HBITMAP;
    begin
      MaskHandleNeeded; // voir dessous
      Result := FMaskHandle;
    end; // et on retourne avec les 10 chiffres du handle
     
    procedure TCustomBitmap.MaskHandleNeeded;
    begin
      if FMaskHandle <> 0 then Exit; // souris sur FMaskHandle -> 3068503040, on sort
     
     
    // ensuite on entre dans 
    function TCustomBitmap.GetBitmapHandle: HBITMAP;
    begin
      BitmapHandleNeeded; // voir dessous
      Result := FSharedImage.FHandle; // souris sur Result -> 3068503040
    end; // et au lieu de retourner dans lzimg.LoadFromBitmap(Bmp.Handle,Bmp.MaskHandle,W,H); c'est l'erreur qui s'affiche. Pourquoi ? Mystère...
     
     
    procedure TRasterImage.BitmapHandleNeeded;
    begin
      if BitmapHandleAllocated then exit; // testé dessous, c'est True donc on sort
     
    function TCustomBitmap.BitmapHandleAllocated: boolean;
    begin
      // for custombitmap handle = bitmaphandle
      Result := FSharedImage.FHandle <> 0; // 3068502656 donc Result True
    end;
    Voilà, je ne sais pas aller plus loin plus profond, désolé.


    Citation Envoyé par BeanzMaster Voir le message
    Par contre dans CreateData tu as jeté un oeil au cas où ?
    bah, ça génère des datas de "service" (Size, MaskSize).
    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

  17. #37
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Oui je suis en 32 bits et oui, c'est toujours la 1.4, mais ce que je ne capte pas du tout c'est que tu dis ce soir que chez moi c'est cette ligne qui fait planter alors que cet après-midi tu disais que ça fonctionnait bien. C'est quoi ce délire ?

    Bref, je viens de m'amuser à creuser ce crash :
    C'est a partir des dimensions que ça foire

    W := 32768;
    H := 16384;

    Sinon après de là ou tu est dans l'analyse faudrait regarder ce que se cache derrière "FSharedImage"


    Bon je viens de retourner dans mes code sur le bmp histoire de vérifier cette histoire de taille

    Citation Envoyé par Ludelphi7 Voir le message
    Si tu crées un bmp 32000*32000*4 en v1 (4Go sur disque), ton champ entete de fichier n'indiquera pas la bonne taille = 4 096 000 054 mais une taille erronée = -198 967 242.
    Idem pour le champ TailleData qui sera tout aussi faux.
    Que tu trouves des astuces pour lire et écrire de tels fichiers n'empèche pas le fait que tu crées des fichiers qui ne sont plus valides, qui comportent de fausses indications sur les tailles déclarées.
    Prévenir les autres programmeurs revient à créer un nouveau format maison "v1plus" ou "BMP_BeanMaster" dans lequel on se met d'accord qu'il ne faut plus tenir compte de ces champs non valides, mais faire à la place faire une routine genre TailleData=TailleOcupée sur disque (int64) -54.
    Ne pas prévenir revient à lâcher dans la nature des fichiers qui risquent de faire bugger toutes les applis qui se fient à l'intégrité des fichiers lus, applis garanties uniquement sur les fichiers qui respectent le format.
    Respecter un format ne se limite pas à écrire au bon endroit, mais aussi y écrire des valeures exactes exemptes de toute fausse indication.

    ludo
    Alors voila mon en-tête

    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
     
     //En-têtes BMP Windows  V1
      //      biSize: LongWord;               // Taille de l'en-tête  = 40 octets
      TGLZWindowsBMPInfoHeaderV1 = Packed Record
        biWidth: Longint;               // Largeur de l'image en pixels
        biHeight: Longint;              // Hauteur de l'image en pixels
        biPlanes: Word;                 // Nombre de Plans de couleur  = 1
        biBitCount: Word;               // Nombre de bits par pixel
        biCompression: Longword;        // Type de compression
        biSizeImage: Longword;          // Taille de l'image  AVEC LE PADDING---> C'est bien ce paramètre ?
        biXPixelsPerMeter: Longint;     // Nombre de pixel horizontal par mètre
        biYPixelsPerMeter: Longint;     // Nombre de pixel vertical par mètre
        biClrUsed: Longword;            // Nombre de couleurs utilisées (0 = toutes)
        biClrImportant: Longword;       // Nombre de couleurs importantes (0 = toutes)
      End;
    Tu fais bien référence à ce paramètre : biSizeImage: Longword; parce que type Longword = 0..4294967295;
    On se rapproche des 4 Go là, non ?
    • "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. #38
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    C'est a partir des dimensions que ça foire

    W := 32768;
    H := 16384;
    Ouf, je comprends mieux !
    Sauf que chez moi ça a foiré avant...
    (et grosse flemme de chercher où -- j'attends la 1.8)

    Citation Envoyé par BeanzMaster Voir le message
    Sinon après de là où tu es dans l'analyse, faudrait regarder ce que se cache derrière "FSharedImage"
    Rien, il ne se cache rien de particulier :
    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
    // dans Graphics :
      TRasterImage = class(TGraphic)
      protected
        FSharedImage: TSharedRasterImage;
     
    // puis
      TSharedRasterImage = class(TSharedImage)
      private
        FHandle: THandle; // generic type, can be HBITMAP or HICON or ....
     
    // et enfin
      { TSharedImage -  base class for reference counted images }
     
      TSharedImage = class
      private
        FRefCount: Integer;
      protected
        procedure Reference; // increase reference count
        procedure Release;   // decrease reference count
        procedure FreeHandle; virtual; abstract;
        property RefCount: Integer read FRefCount;
      public
        function HandleAllocated: boolean; virtual; abstract;
      end;
    Je suspecte le bug dans les calculs de LoadFromBitmap, alors creusons...

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    procedure TLazIntfImage.LoadFromBitmap(ABitmap, AMaskBitmap: HBitmap;
      AWidth: integer; AHeight: integer);
    var
      R: TRect;
      RawImage: TRawImage;
      Desc: TRawImageDescription;
    begin
      if not RawImage_DescriptionFromBitmap(ABitmap, Desc) then
        raise FPImageException.Create('Failed to get raw image description from bitmap');
     
      if AWidth < 0 then AWidth := Desc.Width;
      if AHeight < 0 then AHeight := Desc.Height;
      R := Rect(0, 0, AWidth, AHeight);
      if not RawImage_FromBitmap(RawImage, ABitmap, AMaskBitmap, @R) then // c'est cette ligne qui plante <-------------- !
        raise FPImageException.Create('Failed to get raw image from bitmap');
     
      SetRawImage(RawImage);
    end;
     
    // dans lclintf.inc :
    function RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect): Boolean;
    begin
      Result := WidgetSet.RawImage_FromBitmap(ARawImage, ABitmap, AMask, ARect);
    end;
     
    // et dans gtk2lclintf.inc
    function TGtk2WidgetSet.RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect): Boolean;
    var
      GdiBitmap: PGDIObject absolute ABitmap;
      GdiMask: PGDIObject absolute AMask;
      Drawable: PGdkDrawable;
      Bitmap: PGdkBitmap;
    begin
      //...
      try
        // get rawimage for Bitmap
        case GdiBitmap^.GDIBitmapType of
          gbBitmap: begin
            Drawable := GdiBitmap^.GDIBitmapObject;
            Bitmap := nil;
          end;
          gbPixmap: begin // on passe ici
            Drawable := GdiBitmap^.GDIPixmapObject.Image; // Drawable = nil après exécution
            Bitmap := GdiBitmap^.GDIPixmapObject.Mask; // Bitmap = nil après exécution
          end;
          gbPixbuf: begin
            Result := RawImage_FromPixbuf(ARawImage, GdiBitmap^.GDIPixbufObject, ARect);
            Exit;
          end;
        else
          DebugLn('WARNING: [TGtk2WidgetSet.RawImage_FromBitmap] Unknown GDIBitmapType');
          Exit;
        end;
        Result := RawImage_FromDrawable(ARawImage, Drawable, Bitmap, ARect);
     
    // et enfin ça envoie dans gtk2widgetset.inc :
    function TGtk2WidgetSet.RawImage_FromDrawable(out ARawImage: TRawImage; ADrawable, AAlpha: PGdkDrawable; ARect: PRect): boolean;
    begin
      Result := False;
      if ADrawable = nil then
        RaiseGDBException('TGtk2WidgetSet.RawImage_FromDrawable'); // voilà l'erreur affichée ! Sauf que ce texte ne remonte pas, pour nous mettre sur la piste...
    La grande question (pour moi), c'est pourquoi on passe par gbPixmap et pas par gbBitmap dans le case de RawImage_FromBitmap...
    On trouve, dans Gtk2Def, les lignes suivantes :
    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
      PGDIObject = ^TGDIObject;
      TGDIObject = record
        //...
        case GDIType: TGDIType of
          gdiBitmap: (
            Depth: integer;
            SystemVisual : Boolean;
            Visual : PGDKVisual;
            Colormap : PGDKColormap;
            case GDIBitmapType: TGDIBitmapType of // TGDIBitmapType = (gbBitmap, gbPixmap, gbPixbuf);
              gbBitmap: (GDIBitmapObject: PGdkBitmap); // pixmap with depth 1
              gbPixmap: (GDIPixmapObject: record // normal pixmap
                          Image: PGdkPixmap;     // imagedata
                          Mask: PGdkBitmap;      // the mask for images with 1 bit alpha and pixmap not supporting alpha
                        end);
              gbPixbuf: (GDIPixbufObject: PGdkPixbuf);
          );
    La solution serait peut-être du côté de TGDIBitmapType mais je n'ai pas trouvé ce qui le déterminait.
    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

  19. #39
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par Ludelphi7 Voir le message
    Concernant TailleFichier, cette valeur devient archi-fausse à cause des 54 octets de l’entête pour une taille bmp 32768x16384x4, (maudit entête !).
    Elle redevient valide pour 32768x16383x4 -> TailleFichier = 2^31-32768+54 < 2Go
    Citation Envoyé par Ludelphi7 Voir le message
    [--snip--] mais faire à la place faire une routine genre TailleData=TailleOcupée sur disque (int64) -54.
    ATTENTION !

    On peut rencontrer la valeur 122 (et peut-être d'autres, alors, à ce compte-là...), démonstration avec une routine dont l'origine remonte à l'ami Thierry William :
    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
    procedure TForm1.Button5Click(Sender: TObject); // Thierry
    var
      cible,cible2: TBitmap;
      bs: TBytesStream;
    begin
      If not opd.Execute Then Exit; // OpenPictureDialog
      // lecture
      bs:= TBytesStream.Create;
      cible:= TBitmap.Create;
      cible.loadfromfile(opd.FileName); // image 150x100
      showmessage(inttostr(cible.RawImage.Datasize)); // 45200 = 100 lignes de 452 bytes, soit 450 (150 px x 3 bytes par px) + 2 de padding
      cible.SaveToStream(bs);
      bs.position:=0;
     
      // écriture d'après bs
      cible2:= TBitmap.Create;
      cible2.pixelformat:= pf24bit;
      //l'une ou l'autre -> image ok
      //cible2.pixelformat:= pf32bit;
      cible2.Width :=cible.Width;
      cible2.Height:=cible.Height;
      cible.free;
      showmessage(inttostr(bs.Size)); // 45322 = taille du bitmap source + 122 (header)
      cible2.LoadFromStream(bs, bs.Size);
      image1.picture.assign(cible2);
      cible2.free;
      bs.free;
    end;
    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

  20. #40
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Citation Envoyé par Jipété Voir le message
    j'exécute avec 32767 et 16383 et tu sais quoi ?
    Paf !
    Nom : sigfpe.png
Affichages : 624
Taille : 15,0 Ko
    Citation Envoyé par Jipété Voir le message
    La solution serait peut-être du côté de TGDIBitmapType mais je n'ai pas trouvé ce qui le déterminait.
    Ben non, la solution est planquée Dieu seul sait où (Lazare ! Lève-toi et viens nous dire où Lazarus merdouille !) car je viens de faire un essai avec W = 4000 et H = 3000 et ça passe sans problèmes...

    Donc les limites sont fluctuantes (and mergitur si je peux me permettre ce jeu de mots [mais au point où on en est, why not ?]), aléatoires et pifomètriques...
    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

Discussions similaires

  1. [HTML 5] Taille maximal d'une image
    Par Stefan0 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 27/11/2011, 18h01
  2. Fixer la taille maxi d'une image
    Par franck.thibault dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 14/08/2006, 14h00
  3. récupérer la taille totale d'une image avant chargement
    Par sorenson dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 25/06/2006, 15h50
  4. Taille max d'une image
    Par Risike dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 04/05/2006, 18h16
  5. Taille maximal d'une chaine de caractère...
    Par nguthans dans le forum Langage
    Réponses: 1
    Dernier message: 01/03/2006, 17h58

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