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

Langage Delphi Discussion :

Redimensionnement d'image


Sujet :

Langage Delphi

  1. #1
    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 044
    Points
    15 044
    Par défaut Redimensionnement d'image
    Bonjour,

    sur cette page on peut trouver des routines 1 de redimensionnement d'image qui se compilent et s'exécutent bien sous D7 perso (sous Win2000) sauf une (la première), qui ignore le redimensionnement horizontal
    Nom : squash.png
Affichages : 225
Taille : 38,5 Ko
    (original à gauche, réduction à droite)

    Quelle peut bien être l'instruction manquante ?
    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
    procedure Squash(bmpS, bmpD: TBitmap);
    var
      scanlS, scanlD: Pointer;
      widthS, widthD: integer;
      yS, sInc, yD: integer;
    begin
      {assume correct size for bitmaps and assume pixelformat of 24bpp
      for both. These could be precomputed but it wouldnt save much time}
      widthS := integer(bmpS.Scanline[1]) - integer(bmpS.Scanline[0]);
      widthD := integer(bmpD.Scanline[1]) - integer(bmpD.Scanline[0]);
     
      {how many scanlines to move down in source, per dest scanline}
      sInc := (bmpS.Height shl 16) div bmpD.Height;
     
      scanlS := bmpS.Scanline[0];
      scanlD := bmpD.Scanline[0];
     
      yS := 0;
      for yD := 0 to bmpD.Height - 1 do
      begin
        {copy scanline}
        Move(scanlS^, scanlD^, bmpD.Width * 3); {assumes pf24bit}
        inc(yS, sInc);
        {move down whole number of scanlines}
        inc(integer(scanlS), widthS * (yS shr 16));
        {and update yS to reflect the move}
        dec(yS, yS and $FFFF0000);
        inc(integer(scanlD), widthD);
      end;
    end;


    1 : si certains veulent en tester d'autres, il y a un microscopique bug de typo dans la routine 2, invisible tant qu'on ne réorganise pas un peu le code, comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    pc[x*3 +2] := (Col1b*w1 + Read[(t+1)*3 +2]*w2 + Col2b*w3 + Read2[(t+1)*3 +2] * w4) shr 15;
    pc[x*3 +1] := (Col1g*w1 + Read[(t+1)*3 +1]*w2 + Col2g*w3 + Read2[(t+1)*3 +1] * w4) shr 15;
    pc[x*3   ] := (Col1r*w1 + Read2[(t+1)*3   ]*w2 + Col2r*w3 + Read2[(t+1)*3   ] * w4) shr 15;
    correction (dernière ligne, suppression d'un "2" en trop) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    pc[x*3 +2] := (Col1b*w1 + Read[(t+1)*3 +2]*w2 + Col2b*w3 + Read2[(t+1)*3 +2] * w4) shr 15;
    pc[x*3 +1] := (Col1g*w1 + Read[(t+1)*3 +1]*w2 + Col2g*w3 + Read2[(t+1)*3 +1] * w4) shr 15;
    pc[x*3   ] := (Col1r*w1 + Read[(t+1)*3   ]*w2 + Col2r*w3 + Read2[(t+1)*3   ] * w4) shr 15;
    Maintenant attention : je me suis rendu compte que ces routines à base de Scanline produisaient des résultats très moches (en bas sur l'image) quand il s'agissait de travailler sur du texte, et que la fonction StretchDraw était sur ce coup-là bien plus performante (en haut), pour une durée d'exécution (sous Lazarus et Linux) similaire.
    Démonstration avec un fichier de test créé par mes soins (800x600, réduit à 400x300) :
    Nom : compar_routines.jpg
Affichages : 317
Taille : 83,9 Ko
    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. #2
    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
    Citation Envoyé par Jipété Voir le message
    sauf une (la première), qui ignore le redimensionnement horizontal
    Squash veut dire écraser et c'est exactement ce que fait cette routine en copiant une ligne (complète) sur N.

  3. #3
    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 044
    Points
    15 044
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Squash veut dire écraser et c'est exactement ce que fait cette routine en copiant une ligne (complète) sur N.
    1. quel est l'intérêt de faire le boulot à moitié et sans le préciser ?
    2. écraser, d'accord, mais quand j'écrase une patate pour en faire de la purée, euh, c'est toute la patate qui est écrasée !
    3. la question d'origine est "I would like to resize this bitmap", l'OP n'a pas précisé "dans une seule direction"...
    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
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 844
    Points : 11 274
    Points
    11 274
    Billets dans le blog
    6
    Par défaut
    Il ne manque rien : elle n'est juste pas conçue pour ça !
    Elle recopie 1 début de ligne tous les y, réduisant la hauteur proportionnellement, mais en conservant l'échelle horizontale...
    Il faudrait changer le Move(début de ligne) par une recopie sur cette ligne de 1 pixel sur x (ratio horizontal), ce qui risque d'être très lent et très moche !
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    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 044
    Points
    15 044
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Il ne manque rien : elle n'est juste pas conçue pour ça !


    Extrait du tout début de la page, à gauche mes précisions :

    Nom : qr.png
Affichages : 217
Taille : 24,1 Ko

    Après tout, il y a une erreur dans la 2e routine, il peut bien y en avoir une autre dans la 1re, nan ?

    Citation Envoyé par tourlourou Voir le message
    Il faudrait changer le Move(début de ligne) par une recopie sur cette ligne de 1 pixel sur x (ratio horizontal), ce qui risque d'être très lent et très moche !
    Et c'est bien ce que je voudrais voir, d'où ce post, parce que je me prends les pieds dans le tapis avec cette histoire de ratio
    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

  6. #6
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 844
    Points : 11 274
    Points
    11 274
    Billets dans le blog
    6
    Par défaut
    non testé, à la louche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    HorRatio :=widthS DIV widthD; 
    //...
    for largeur:=0 to bmpD.Width-1
    do begin
      Move(scanlS^, scanlD^, 3);
      Inc(integer(scanlS), 3*HorRatio); 
      Inc(integer(scanlD), 3); 
    end;
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  7. #7
    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 044
    Points
    15 044
    Par défaut
    Bonsoir,
    Citation Envoyé par tourlourou Voir le message
    non testé, à la louche :
    2 choses :
    1. concernant le ratio, les autres routines utilisent plutôt ratio := source div dest, me suis donc permis d'inverser le tien, mais ça ne change pas l'étendue de la catastrophe...
    2. car, oui, ne sachant ni où ni comment insérer tes 3 petites lignes, autant dire que je n'arrive à rien


    Je remets la partie cruciale de la routine d'origine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    for yD := 0 to bmpD.Height - 1 do
    begin
      {copy scanline}
      Move(scanlS^, scanlD^, bmpD.Width * 3); {assumes pf24bit}
      inc(yS, sInc);
      {move down whole number of scanlines}
      inc(integer(scanlS), widthS * (yS shr 16));
      {and update yS to reflect the move}
      dec(yS, yS and $FFFF0000);
      inc(integer(scanlD), widthD);
    end;
    Je peux supposer que le début devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for yD := 0 to bmpD.Height - 1 do
    begin
      for largeur:=0 to bmpD.Width-1 do
      begin
        {copy scanline}
        Move(scanlS^, scanlD^, 3);
    Mais après ? Me faut-il remplacer "mes" lignes inc(integer(scanlX)... par les tiennes ?
    Ou je me contente de rajouter tes deux Inc et ton end, et je continue avec le reste de la routine ? Testé les deux manières, négatif.

    En utilisant ce que tu as posté (qui équivaut, pour moi, à la "reconstruction" de chaque ligne), inséré avant inc(yS, sInc);, j'obtiens ça :
    Nom : manip_yves.png
Affichages : 231
Taille : 1,5 Ko

    Suis un peu en plein brouillard, là...

    Bon, si t'as pas le temps laisse tomber, c'était plus une curiosité qu'autre chose.
    C'est dommage parce que je suis sûr qu'on n'est pas loin du but
    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. #8
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 844
    Points : 11 274
    Points
    11 274
    Billets dans le blog
    6
    Par défaut
    Vite vu, qqch comme ça, mais j'ai du mal à croire que ça puisse donner un résultat regardable ! C'est bien sûr au contrôle de bornes près, au risque de m'être fichu dedans sur les indices, à 1 près, et finalement, de ne pas avoir compris le code initial dont je ne vois pas bien la fonction des shl 16 et autres !
    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 Squash(bmpS, bmpD: TBitmap);
    var
      scanlS, scanlD: Pointer;
      widthS, widthD: integer;
      yS, sInc, yD, xD: integer;
      HorzRatio, VertRatio : integer;
    begin
      widthS := integer(bmpS.Scanline[1]) - integer(bmpS.Scanline[0]);
      widthD := integer(bmpD.Scanline[1]) - integer(bmpD.Scanline[0]);
      HorzRatio := widthS div widthD; // combien de lignes de la source pour une dans la destination
      VertRatio := bmpS.Height div bmpD.Height; // combien de lignes de la source pour une dans la destination
     
     
      for yD := 0 to bmpD.Height - 1 do
      begin
        scanlD := bmpD.Scanline[yD];
        scanlS := bmpS.Scanline[yD*VertRatio];
     
        for xD:=0 to bmpD.Width-1 do // pour chaque pixel de la destination
        begin
          Move(scanlS^, scanlD^, 3); // on copie 1 pixel de la source (3 octets en pf24Bit)
          Inc(integer(scanlS), 3*HorzRatio); // et on en saute x dans la source en fonction du ratio (pê plutôt 3*(HorzRatio-1) d'ailleurs...)
          Inc(integer(scanlD), 3); // on passe juste au suivant dans la destination
        end;
     
      end;
     
    end;
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  9. #9
    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
    Citation Envoyé par tourlourou Voir le message
    ...et finalement, de ne pas avoir compris le code initial dont je ne vois pas bien la fonction des shl 16 et autres !
    C'est un multiplicateur (216) qui a pour but de limiter l'arrondi sur le div. shr dans la boucle remet la valeur "normale" (la re-divise par 216).

    C'est plus performant que de diviser / pour obtenir un réel avant d'y appliquer un arrondi (trunc).

    Ca, ça ne joue pas bmpS.Height div bmpD.Height. Pour un bmpD de 100, bmpS peut varier de 100 à 199 pour un même ratio

  10. #10
    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 044
    Points
    15 044
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          Inc(integer(scanlS), 3*HorzRatio); // et on en saute x dans la source en fonction du ratio (pê plutôt 3*(HorzRatio-1) d'ailleurs...)
    Surtout pas le calcul en commentaire, c'est ce qu'on voit en bas à droite
    Nom : ratios.png
Affichages : 209
Taille : 179,7 Ko (image globalement réduite)

    Citation Envoyé par Andnotor Voir le message
    Ca, ça ne joue pas bmpS.Height div bmpD.Height. Pour un bmpD de 100, bmpS peut varier de 100 à 199 pour un même ratio
    Je pense que j'illustre ce que tu veux dire, avec le code d'Yves affiché en haut à droite. En examinant attentivement ce qui est visible, je le retrouve sur l'original (rectangle rouge) et je constate que ce rectangle a une largeur de 400 alors que je demande 200, qui correspond au bitmap cible.

    J'ai planté un ShowMessage(inttostr(HorzRatio) +' '+ inttostr(VertRatio)); qui m'affiche 2 2, c'est pas terrible !

    En fait il n'y a pas de solution simple, on dirait, et je propose donc de laisser tomber, à moins que quelqu'un ait une idée géniale.

    Et si je rajoute la couche "de toute façon sous Linux/Lazarus ton code me donne une image toute noire", je pense qu'on n'est pas rendu, même si je ne suis pas dans le bon forum
    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. #11
    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 044
    Points
    15 044
    Par défaut
    Bonsoir,

    j'ai beaucoup gambergé à ça toute la journée, je me demande bien ce qui peut coincer...

    J'ai essayé de résumer ma pensée ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    scanlS := bmpS.ScanLine[0]; // 1re ligne du fichier image (source)
    for yD := 0 to bmpD.Height-1 do begin // balayage vertical des lignes
      for xD := 0 to bmpD.Width-1 do begin // il faut compacter les pixels de la ligne
        cb:=0; cg:=0; cr:=0; ca:=0; // 4 cardinaux temporaires pour moyennes
        for i := 0 to HorzRatio-1 do begin // balayage d'un bloc de pixels de la source
          cb := cb + byte(scanlS^); inc(scanlS, 1);
          cg := cr + byte(scanlS^); inc(scanlS, 1);
          cr := cr + byte(scanlS^); inc(scanlS, 1);
          ca := ca + byte(scanlS^); inc(scanlS, 1);
        end; 
        // stockage de la moyenne des px-source dans le px-destination
        PixelsInDest[xD] := BGRAtoTBGRAQuad(cb div HorzRatio, cg div HorzRatio, cr div HorzRatio, ca div HorzRatio);
      end; // for xD
      // suite
    Et le problème que je rencontre, c'est qu'en y allant en pas-à-pas après avoir ouvert un fichier certifié avec canal Alpha, lorsque je regarde les variables cb cg cr ca, il n'y en a aucune qui m'indique 255, qui devrait correspondre à l'opacité totale de mon fichier.

    J'en conclus que je ne me balade pas dans les couleurs du fichier mais alors, où suis-je ?
    Et comment vraiment parcourir le fichier ?

    Note : je me prendrai la tête avec les histoires d'arrondis et de précision des singles versus integers quand je serai sûr de repérer les bytes "canal Alpha", ce qui n'est donc pas le cas pour le moment...

    PS : oui, je suis un peu à cheval entre Delphi et Lazarus, entre Windows et Linux, mais bon, il est juste question de parcourir un fichier pour lui récupérer ses pixels.
    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

  12. #12
    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
    Toujours les mêmes problèmes (et les mêmes questions)

    bmpS.ScanLine[0] n'est pas la première ligne de l'image mais la dernière. La deuxième ligne lue est au-delà du tableau de pixels.

    inc(scanlS, 1) ne tient pas compte du padding, il y a (ou peut y avoir) décalage.

  13. #13
    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 044
    Points
    15 044
    Par défaut
    Bonjour,

    Citation Envoyé par Andnotor Voir le message
    Toujours les mêmes problèmes (et les mêmes questions)


    Citation Envoyé par Andnotor Voir le message
    bmpS.ScanLine[0] n'est pas la première ligne de l'image mais la dernière. La deuxième ligne lue est au-delà du tableau de pixels.
    je sais bien, et à te lire on penserait qu'il faut y aller avec for yD := bmpD.Height - 1 downto 0 do ... , pourtant, quand on regarde les quelques lignes de la proc d'origine et particulièrement la 19 :

    Nom : scanline_origine.png
Affichages : 199
Taille : 11,7 Ko

    on ne peut qu'être perplexe et se gratter longuement le menton...


    Citation Envoyé par Andnotor Voir le message
    inc(scanlS, 1) ne tient pas compte du padding, il y a (ou peut y avoir) décalage.
    Oui, j'en suis arrivé à la même conclusion ce matin, et je vais même plus loin : si ça se trouve, c'est pour ça qu'il manque à cette routine toute la partie "compression horizontale" car c'est d'une complexité sans nom, entre les différences de plateformes et les fichiers 24/32 bits, ça en devient imbuvable !

    Je ne peux pas cocher car ça ne l'est pas, merci cependant pour les pistes de réflexion.
    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

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 021
    Points : 40 932
    Points
    40 932
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Jipété Voir le message
    Oui, j'en suis arrivé à la même conclusion ce matin, et je vais même plus loin : si ça se trouve, c'est pour ça qu'il manque à cette routine toute la partie "compression horizontale" car c'est d'une complexité sans nom, entre les différences de plateformes et les fichiers 24/32 bits, ça en devient imbuvable !
    c'est ce que j'ai pensé dès le début de la discussion
    Je ne peux pas cocher car ça ne l'est pas, merci cependant pour les pistes de réflexion.
    sauf si tu peux faire une rotation à 90° de l'image retaillée, que tu appliques la routine et que tu fasses la rotation contraire mais du coup, pour le "Quickly" on peut repasser
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  15. #15
    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
    En rapport au premier exemple.

    Citation Envoyé par Jipété Voir le message
    je sais bien, et à te lire on penserait qu'il faut y aller avec for yD := bmpD.Height - 1 downto 0 do ... , pourtant, quand on regarde les quelques lignes de la proc d'origine et particulièrement la 19 :
    La valeur de boucle yD n'a aucune importance puisque pas utilisée dans l'indexation.

    Citation Envoyé par Jipété Voir le message
    on ne peut qu'être perplexe et se gratter longuement le menton...
    En mémoire, la ligne 1 est placée avant la ligne 0. integer(Scanline[1]) -integer(Scanline[0]) donne donc une valeur négative, widthS et widthD sont négatifs. inc(integer(scanlD), widthD) revient à décrémenter le pointeur

    Il part de la ligne 0 et revient en arrière. Si tu veux allez en avant, il faut calculer le pas par integer(Scanline[0]) -integer(Scanline[1]) (valeur positive) et partir de Scanline[Height -1].

  16. #16
    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
    Le p'tit exercice de fin d'après-midi

    Cette routine fonctionne en 8, 16, 24 et 32 bits (pas de formats "exotiques").
    S'assurer que les deux images ont le même PixelFormat avant appel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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
    procedure StretchDown(BmpS, BmpD: TBitmap);
    var
      PS, PD: PByte;
      WidthS, WidthD: integer;
      PaddingS, PaddingD :integer;
      NbBytes, IncX, IncY, X, Y: integer;
     
    begin
      //Largeur d'une ligne y compris Padding
      WidthS := integer(BmpS.Scanline[0]) -integer(BmpS.Scanline[1]);
      WidthD := integer(BmpD.Scanline[0]) -integer(BmpD.Scanline[1]);
     
      //Nombre d'octets par pixel
      NbBytes := WidthS div BmpS.Width;
     
      //Calcul des incréments
      IncX := ((BmpS.Width shl 16) div BmpD.Width) shr 16;
      //IncY -1 puisqu'on aura déjà décalé d'une ligne à la fin de la boucle X
      IncY := ((BmpS.Height shl 16) div BmpD.Height) shr 16 -1;
     
      //Calcul des alignements
      //Dans le cas de la source, il faut tenir compte du
      //fait que le dernier pixel lu ne sera pas à Width -1
      PaddingS := WidthS mod (BmpD.Width *NbBytes *IncX);
      PaddingD := WidthD mod BmpD.Width;
     
      //Début du tableau de pixels
      PS := BmpS.Scanline[BmpS.Height -1];
      PD := BmpD.Scanline[BmpD.Height -1];
     
      for Y := 0 to BmpD.Height -1 do
      begin
        for X := 0 to BmpD.Width -1 do
        begin
          Move(PS^, PD^, NbBytes);
          inc(PS, IncX *NbBytes);
          inc(PD, NbBytes);
        end;
     
        inc(PS, PaddingS +WidthS *IncY);
        inc(PD, PaddingD);
      end;
    end;

  17. #17
    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 044
    Points
    15 044
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    S'assurer que les deux images ont le même PixelFormat avant appel.
    Les deux bitmaps, plutôt, je suppose ?

    Comme ça : ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      bm1.PixelFormat := pf24bit;
      bm2.PixelFormat := pf24bit;
    Je dois être maudit (le fichier est un 24 bits) :

    Nom : test_andnotor.png
Affichages : 181
Taille : 137,6 Ko

    Résultat (sans changer une virgule) sous W2k/D7...

    @Sergio : c'est pas bête ton idée ! Je n'y avais pas du tout pensé, du coup me voilà parti à étudier les exemples pêchés chez efg ! T'as pas vu passer ma boîte d'aspirine ?

    L'informatique c'est magique, je trouve : tu veux faire 1 truc, t'es obligé d'en étudier 10, et pour chacun va falloir en étudier 10 autres, etc. Un puits sans fond...
    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

  18. #18
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 410
    Points : 5 801
    Points
    5 801
    Par défaut
    salut

    tu perd des détail en haut et a droite
    il te manquerais pas un incrément dans chaque boucle ?
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  19. #19
    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
    Bien sûr ! Il faut prendre en compte X et Y et appliquer l'arrondi (shr) après.
    (Je n'avais testé que sur des tailles multiples...)

    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
    procedure StretchDown(BmpS, BmpD: TBitmap);
    var
      PS, PD: PByte;
      WidthS, WidthD: integer;
      PaddingD :integer;
      NbBytes, IncX, IncY, X, Y: integer;
      StepX, StepY :integer;
     
    begin
      //Largeur d'une ligne y compris Padding
      WidthS := integer(BmpS.Scanline[0]) -integer(BmpS.Scanline[1]);
      WidthD := integer(BmpD.Scanline[0]) -integer(BmpD.Scanline[1]);
     
      //Nombre d'octets par pixel
      NbBytes := WidthS div BmpS.Width;
     
      //Calcul du pas
      StepX := (BmpS.Width shl 16) div BmpD.Width;
      StepY := (BmpS.Height shl 16) div BmpD.Height;
     
      //Calcul de l'alignement
      PaddingD := WidthD mod BmpD.Width;
     
      //Début du tableau de pixels
      PS := BmpS.Scanline[BmpS.Height -1];
      PD := BmpD.Scanline[BmpD.Height -1];
     
      for Y := 0 to BmpD.Height -1 do
      begin
        IncY := (Y *StepY) shr 16 *WidthS;
        inc(PS, IncY);
     
        for X := 0 to BmpD.Width -1 do
        begin
          IncX := (X *StepX) shr 16 *NbBytes;
          inc(PS, IncX);
     
          Move(PS^, PD^, NbBytes);
     
          dec(PS, IncX);
          inc(PD, NbBytes);
        end;
     
        dec(PS, IncY);
        inc(PD, PaddingD);
      end;
    end;

  20. #20
    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 044
    Points
    15 044
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    (Je n'avais testé que sur des tailles multiples...)
    Voyou !

    Bravo

    Nom : andnotor_success.png
Affichages : 171
Taille : 139,6 Ko



    Plus qu'à trouver comment faire fonctionner tout ça sous Linux/Laz.

    Demain il fera jour !

    Mille millions de mercis, Andnotor
    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

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. instruction systeme dans une routine
    Par flamel dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 21/08/2013, 13h29
  2. [WD12] Info manquante dans le code source d'une page web
    Par zouzoukha dans le forum WinDev
    Réponses: 12
    Dernier message: 18/06/2012, 05h21
  3. System.Web manquant dans Silverlight ?
    Par narglix dans le forum Silverlight
    Réponses: 4
    Dernier message: 23/03/2010, 16h15
  4. [ImageMagick] Problème dans le code pour redimensionner une image
    Par pierrot10 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 08/06/2007, 15h06
  5. Licence MySql en tant que BD dans une application web
    Par Volta dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 26/02/2004, 15h38

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