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. #21
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 848
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 848
    Points : 15 264
    Points
    15 264
    Par défaut
    Bonjour,

    Ma contribution, la compilation conditionnelle en fonction du compilo (oui, je sais, nous sommes dans le monde Delphi, ici, mais ce genre de code peut être utile à plein de gens, alors bon..)

    Testé sous Linux / Laz 1.4, XP / Laz 1.6, Win2000 / D7 perso
    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
    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
      {$IFDEF FPC}
      widthS := uint(bmpS.RawImage.GetLineStart(1)) - uint(bmpS.RawImage.GetLineStart(0));
      widthD := uint(bmpD.RawImage.GetLineStart(1)) - uint(bmpD.RawImage.GetLineStart(0));
      {$ELSE} // D7
      WidthS := integer(BmpS.Scanline[0]) -integer(BmpS.Scanline[1]);
      WidthD := integer(BmpD.Scanline[0]) -integer(BmpD.Scanline[1]);
      {$ENDIF}
     
      //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 des alignements
      PaddingD := WidthD mod BmpD.Width;
     
      //Début du tableau de pixels
      {$IFDEF FPC}
      bmpD.BeginUpdate();
      PS := bmpS.RawImage.GetLineStart(0);
      PD := bmpD.RawImage.GetLineStart(0);
      {$ELSE} // D7
      PS := bmpS.Scanline[BmpS.Height -1];
      PD := bmpD.Scanline[BmpD.Height -1];
      {$ENDIF}
     
      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;
     
      {$IFDEF FPC}
      bmpD.EndUpdate();
      {$ENDIF}
    end;
    J'ai cependant noté à l'exécution, lorsque je compare avec d'autres routines du même type (fin de la page citée dans le 1er post) une différence d'affichage de 1 px dans le sens horizontal et 1 autre px dans le sens vertical.
    Qui a raison, qui a tort ? Pour le moment le mystère reste entier, je note seulement que la routine d'Andnotor est écrite ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      //Calcul du pas
      StepX := (BmpS.Width  shl 16) div BmpD.Width;
      StepY := (BmpS.Height shl 16) div BmpD.Height;
    et plus bas une utilisation de shr 16,

    quand sur la page citée on peut lire, chapitre "Solve 2", :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      xP2 := ((src.Width  - 1) shl 15) div dst.Width;
      yP2 := ((src.Height - 1) shl 15) div dst.Height;
    et plus bas une utilisation de shr 15.

    Ce qui m'ennuie c'est que je ne vois pas de différence en passant Andnotor de 16 à 15


    Les autres "Solve" (3, 4 et 6) utilisent une autre manière de traiter les arrondis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      xscale := dest.Width  / src.Width;
      yscale := dest.Height / src.Height;
    plus des trunc en veux-tu en voilà plus bas dans le code.

    J'aimerais bien savoir de quoi il retourne et uniformiser toutes ces routines de manière à avoir des résultats identiques. Sinon, où va le monde ?


    Ceci étant dit, je reviens à ce que j'ai écrit dans le post d'origine, concernant la qualité esthétique des réductions à base de scanline : c'est une catastrophe pour ce qui concerne le texte, le code d'Andnotor ne fait pas exception à la règle, désolé !
    On ne voit pas de différences avec « l'œil » alors qu'elle est flagrante avec les zones de texte de mon fichier de test :
    Citation Envoyé par Jipété Voir le message
    [...] 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) :
    Pièce jointe 273176
    Et si vous regardez attentivement l'épaule de Lena, vous noterez sur l'image du bas un effet d'escalier plus prononcé que sur celle du haut, ainsi que la couleur qui change un peu (visible aussi au niveau du chapeau, ainsi que la peau, plus claire en bas, plus bronzée en haut).


    Mais l'avantage incontestable de la routine d'Andnotor, c'est sa rapidité ! J'avais une routine notée "FastSmoothResize", la plus rapide de toute, hé bien Andnotor va presque trois fois plus vite !
    Ça peut être utile...
    Encore un grand bravo à lui

    Un dernier mot, promis : à n'utiliser qu'en réduction car en agrandissement, la routine se prend les pieds dans le tapis, sous Linux (pas testé les autres environnements) :
    Nom : car_agrandi.png
Affichages : 111
Taille : 37,8 Ko

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 337
    Points
    13 337
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Ce qui m'ennuie c'est que je ne vois pas de différence en passant Andnotor de 16 à 15
    Tu pourrais même descendre à 8 que tu ne verrais toujours pas grande différence !

    Regarde ce que ça donne en binaire. Pour une largeur de 271 qui passe en 105 (en rouge les bits supprimés lorsqu'on applique shr):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    271 shl 16 div 105 = 0010 1001 0100 1011 1001‬ shr 16 = 0010 = 2
    271 shl 15 div 105 = 0001 0100 1010 0101 1100‬‬ shr 15 = 0010 = 2
    271 shl 8  div 105 = 0000 0000 0010 1001 0100‬‬‬ shr 8  = 0010 = 2
    Citation Envoyé par Jipété Voir le message
    Les autres "Solve" (3, 4 et 6) utilisent une autre manière de traiter les arrondis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      xscale := dest.Width  / src.Width;
      yscale := dest.Height / src.Height;
    plus des trunc en veux-tu en voilà plus bas dans le code.
    C'est possible mais plus gourmand (voir ici). Mais là aussi, il faut tenir compte de X/Y avant d'appliquer le trunc.

    Citation Envoyé par Jipété Voir le message
    concernant la qualité esthétique des réductions à base de scanline : c'est une catastrophe pour ce qui concerne le texte, le code d'Andnotor ne fait pas exception à la règle, désolé !
    Copier un pixel sur N, pas de miracle !
    Je te laisse le soin de calculer la moyenne des points adjacents

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

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, 12h29
  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, 04h21
  3. System.Web manquant dans Silverlight ?
    Par narglix dans le forum Silverlight
    Réponses: 4
    Dernier message: 23/03/2010, 15h15
  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, 14h06
  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, 14h38

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