redimensionner une image [résolu]

wiskywisky Membre
août 2005 modifié dans API AppKit #1
Dans un NSImageView j'affiche une image. Et j'ai un NSSlide pour faire un zoom arrière et avant.

Pour le moment j'arrive à  zoomer mais pas à  dézoomer (ou alors le format h/w n'est plus respecter, il affiche une partie de l'image, etc...).

voici le code de la fonction qui re-dimensionne l'image.
<br />- (IBAction)ResizePicture:(id)sender<br />{<br />//chargement de l&#39;image<br />	NSImage *ImageCopy = [[NSImage alloc] initWithContentsOfFile:[[[PictureOfFilm objectAtIndex:[PictureListFiles selectedRow]] valueForKey:@&quot;path&quot;] stringByExpandingTildeInPath]];<br />//recuperation de la taille d&#39;origine<br />	NSSize size;<br />	size = [ImageCopy size];<br />//calcul de la nouvelle taille<br />	size = NSMakeSize((size.width*([sender floatValue]/10)),(size.height*[sender floatValue]/10));<br />//application de la nouvelle taille<br />	[ImageCopy setSize:size];<br />/affichage<br />	[FilmImageView setImage:ImageCopy];<br />}<br />


J'ai loupé un truc ? B)

Réponses

  • WIMPWIMP Membre
    17:29 modifié #2
    L'idée qui me vient à  première vue, c'est qu'il faudrait que tu mémorises préalablement la size initiale et que tu appliques NSMakeSize sur celle-ci, au lieu de l'appliquer sur la size courante.
    A essayer...
  • AliGatorAliGator Membre, Modérateur
    août 2005 modifié #3
    WIMP : je pense pas que ça pose problème, imageCopy est rechargée à  partir du fichier, donc [imageCopy size] revoie la taille de l'image originale (celle dans le fichier), et donc c'est bien à  partir de cette taille originale qu'il fait les calculs.
    (à  propos, par convention, les variables commencent par une minuscule :P comment ça je chipotte ?? :))

    macintosh_plus, Y'a pas une question de division entière là  dedans ?

    A première vue je vois pas mais bon
    - size.width et size.height sont des entiers (int)
    - floatValue retourne un float, donc pas de soucis
    - quand tu le divises par 10 (entier), un float par un int devrait donner un float
    - un int (size.width ou height) multiplié par (un float)/(un int) tout ça ça doit bien donner un résultat sous forme de float

    Ce ne sont que des éléments de réflexion mais je ne vois que ça comme source de ton problème.... même si pourtant comme montré à  l'instant ça m'a l'air correct.

    Tu peux faire un NSLog de la taille originale + taille zoomée + valeur du slider, dans ta méthode et montrer le résultat ?
  • WIMPWIMP Membre
    17:29 modifié #4
    dans 1124440184:

    WIMP : je pense pas que ça pose problème, imageCopy est rechargée à  partir du fichier, donc [imageCopy size] revoie la taille de l'image originale (celle dans le fichier), et donc c'est bien à  partir de cette taille originale qu'il fait les calculs.
    (à  propos, par convention, les variables commencent par une minuscule :p comment ça je chipotte ?? :))

    Tout à  fait exact, j'avais lu trop vite.

    Pour les minuscules je suis d'accord, surtout qu'en cocoa, le récepteur d'un message peut être soit une classe (Majuscule), soit une variable.
    Si on respecte le convention, la lecture du code s'en trouve facilitée.
    Rigueur n'est pas chipottage
  • AliGatorAliGator Membre, Modérateur
    17:29 modifié #5
    dans 1124441924:

    dans 1124440184:

    WIMP : je pense pas que ça pose problème, imageCopy est rechargée à  partir du fichier, donc [imageCopy size] revoie la taille de l'image originale (celle dans le fichier), et donc c'est bien à  partir de cette taille originale qu'il fait les calculs.
    (à  propos, par convention, les variables commencent par une minuscule :P comment ça je chipotte ?? :))

    Tout à  fait exact, j'avais lu trop vite.

    Pour les minuscules je suis d'accord, surtout qu'en cocoa, le récepteur d'un message peut être soit une classe (Majuscule), soit une variable.
    Si on respecte le convention, la lecture du code s'en trouve facilitée.
    Rigueur n'est pas chipottage
    C'est bien pour ça que j'ai fait la remarque, j'ai presque cru que ImageCopy était une classe, et du coup ça m'a gêné pour lire ;)
  • 17:29 modifié #6
    Faut pas oublier - (void)setScalesWhenResized:(BOOL)flag

    C'est que c'est mieux les variables en minuscule  >:)
  • wiskywisky Membre
    17:29 modifié #7
    merci supermic ça marche mieux ;) il ne découpe plus l'image comme un sauvage.

    Maintenant j'aimerai qu'il re-dimensionne l'image par rapport à  la zone d'affichage en gardant le rapport h/w.
    Pour le zoom je vais remplacer le Slider par un popupbutton.
  • 17:29 modifié #8
    dans 1124440184:

    A première vue je vois pas mais bon
    - size.width et size.height sont des entiers (int)


    Petit correctif. Tout ce qui est NSPoint, NSSize etNSRect utilise des float.
  • fouffouf Membre
    17:29 modifié #9
    Je sais pas si ca peut aider, mais NSView déclare la méthode scaleUnitSquareToSize:.
    Quoi que, ca risque de pixeliser. ???
  • wiskywisky Membre
    17:29 modifié #10
    J'ai trouvé!

    Je calcule un coef entre le plus grand bord de l'image et la taille de ma zone d'affichage correspondant au grand bord.
    J'image s'affiche nickel. :p

    merci  <3 <3 <3 <3 <3 <3 <3
  • AliGatorAliGator Membre, Modérateur
    août 2005 modifié #11
    dans 1124448270:

    Je sais pas si ca peut aider, mais NSView déclare la méthode scaleUnitSquareToSize:.
    Quoi que, ca risque de pixeliser. ???
    Ouuuhh mais à  regarder de plus près celle là ... Pour mon petit problème perso (quoi je joue mon egoà¯ste, moi ? ::)), de redimentionner ma matrix dans ma vue de sorte que ma matrice reste carrée mais aux dimensions maxi pour tenir dans la vue...

    J'avais regardé vite fait ça me semblait pas convenir mais je vais y rejeter un coup d'oeil ;)
    dans 1124454816:

    J'ai trouvé!

    Je calcule un coef entre le plus grand bord de l'image et la taille de ma zone d'affichage correspondant au grand bord.
    J'image s'affiche nickel. :p

    merci  <3 <3 <3 <3 <3 <3 <3 <br />
    Ben pour l'instant c'est ce que je fais pour mes ajustements aussi, je calcule tout à  la main (mon dx et mon dy, pour la position, ainsi que size = MIN(superView's width,superView's height)... Et ça marche aussi très bien ;)
  • wiskywisky Membre
    17:29 modifié #12
    dans 1124454816:

    J'ai trouvé!

    Je calcule un coef entre le plus grand bord de l'image et la taille de ma zone d'affichage correspondant au grand bord.
    J'image s'affiche nickel. :p

    merci  <3 <3 <3 <3 <3 <3 <3 <br />
    Ben pour l'instant c'est ce que je fais pour mes ajustements aussi, je calcule tout à  la main (mon dx et mon dy, pour la position, ainsi que size = MIN(superView's width,superView's height)... Et ça marche aussi très bien ;)


    C'est pas bête le coups de MIN(). Ca peut pas marcher pour mois car il me faut le plus grand donc utiliser MAX(). Mais après comment faire pour savoir avec quel bord divisé puisqu'il ne dit pas si c'est la valeur qui est en position 1 ou 2. voilà  mon code de re-dimensionnement :

    <br />//récuperation de l&#39;image<br />NSImage *imageCopy = [[NSImage alloc] initWithContentsOfFile:[[[PictureOfFilm objectAtIndex:[PictureListFiles selectedRow]] valueForKey:@&quot;path&quot;] stringByExpandingTildeInPath]];<br />	NSSize size,sizebound;<br />	float coef;<br />//récupération de la taille de l&#39;image<br />	size = [imageCopy size];<br />//récupération de la taille de ma zone<br />		sizebound = [FilmImageView bounds].size;<br />//détection de l&#39;orientation et calcul du coef<br />		if(size.height&lt;size.width) coef = size.width / sizebound.width;<br />		else coef = size.height / sizebound.height;<br />		//redimensionnement<br />		if(coef&gt;1.00)//si coef supérieur à  1 agrandissement<br />			size = NSMakeSize((size.width/coef),(size.height/coef));<br />		else //sinon reduction<br />			size = NSMakeSize((size.width*coef),(size.height*coef));<br />	//application de la nouvelle taille<br />	[imageCopy setSize:size];<br />//signale le redimentionnement de l&#39;image<br />	[imageCopy setScalesWhenResized:YES];<br />	//affectation de l&#39;image<br />	[FilmImageView setImage:imageCopy];<br />//raffrechissement<br />	[FilmImageView setNeedsDisplay];
    


    je ne sait pas si ça peut t'aider. en tout cas ça marche ;)
  • AliGatorAliGator Membre, Modérateur
    août 2005 modifié #13
    Wow...

    Voilà  la tronche de mon code pour centrer _matrix dans sa superView :
    /*******************************************************************<br /> *&nbsp; compute the matrix frame (in order the matrix to be centered)&nbsp; *<br /> *******************************************************************/<br />- (NSRect)calcMatrixFrame<br />{<br />	int dx,dy;<br />	int size;<br />	<br />	size = MIN( NSWidth([self frame]) , NSHeight([self frame]) );<br />	<br />	dx = ( NSWidth([self frame]) - size)/2;<br />	dy = (NSHeight([self frame]) - size)/2;<br />	<br />	return NSMakeRect(dx,dy,size,size);<br />}<br /><br />/***********************************<br />*&nbsp; center the matrix on the view&nbsp; *<br />***********************************/<br />- (void)centerMatrixOnView<br />{	<br />	[_matrix setFrame:[self calcMatrixFrame]];<br />		<br />	[self setNeedsDisplay:YES];<br />}<br /><br />/**********************************************<br /> *&nbsp; force recentering the matrix when needed&nbsp; *<br /> **********************************************/<br />- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize<br />{	// called because [self setAutoresizesSubviews:YES];<br />	[self centerMatrixOnView];<br />}
    
    Ceci dit je n'ai pas à  calculer de facteur d'agrandissement.

    Mais j'ai déjà  eu à  faire ça (en RB, mais l'algo est le même).
    Le plus simple à  mon avis est de calculer le coefficient d'agrandissement en x et en y, comme si tu voulais ajuster ton image dans la vue en la déformant, puis de ne garder que le plus petit facteur pour les 2 dimensions, pour ne pas déformer l'image.
    float xScale = [laVue width]/[image width];<br />float yScale = [laVue height]/[image height];<br />float propScale = MIN(xScale, yScale);
    
    Et tu n'as plus qu'à  multipliser les dimensions de ton image (autant W que H) par propScale pour qu'elle soit agrandie au maximum sans déformation.
    Et ce même si ni ta vue ni ton image ne sont rectangulaires, n'ont pas la même orientation (vue plus large que haute et image dans l'autre sens, etc)...
  • Eddy58Eddy58 Membre
    17:29 modifié #14
    Ha oui j'avais fait une méthode dans ce genre, si ça peut aider : :)
    [tt]
    // Méthode de redimensionnement d'image
    -(NSRect)retailleImage:(NSImage *)image cibleDepartX:(float)cDx cibleDepartY:(float)cDy cibleLargeur:(float)cL cibleHauteur:(float)cH
    {
        NSRect rectImage;
        float coeff;

        rectImage.size=[image size];    // Recuperation de la taille de l'image
        // Si la taille de l'image est inferieure a la taille de la cible et que la hauteur de l'image
        // est superieure a la largeur de l'image
        if (rectImage.size.width<cL && rectImage.size.height<cH && rectImage.size.height>rectImage.size.width)
        {
            // Alors adaptation de la taille de l'image a la taille de la cible
            coeff=rectImage.size.height/cH;
            rectImage.size.width=rectImage.size.width/coeff;
            rectImage.size.height=rectImage.size.height/coeff;
        }
        // Si la largeur de l'image est differente de la largeur de la cible
        if (rectImage.size.width != cL)
        {
            // Alors adaptation de la taille de l'image a la taille de la cible
            coeff=rectImage.size.width/cL;
            rectImage.size.width=rectImage.size.width/coeff;
            rectImage.size.height=rectImage.size.height/coeff;
        }
        // Si la hauteur de l'image est superieure a la hauteur de la cible
        if (rectImage.size.height>cH)
        {
            // Alors adaptation de la taille de l'image a la taille de la cible
            coeff=rectImage.size.height/cH;
            rectImage.size.width=rectImage.size.width/coeff;
            rectImage.size.height=rectImage.size.height/coeff;
        }
        // Calcul de l'origine de l'image avec centrage par rapport a l'origine de la cible
        rectImage.origin.x=cDx+(cL-rectImage.size.width)/2;
        rectImage.origin.y=cDy+(cH-rectImage.size.height)/2;
        return rectImage; // Retourne le nouveau rectangle associé a l'image
    }
    [/tt]
  • AliGatorAliGator Membre, Modérateur
    17:29 modifié #15
    Hé bé vos codes m'ont l'air bien compliqués !
    (Et Eddy, pourquoi ne pas utiliser NSMakeSize et NSMakeRect ? enfin bref)

    Mes 3 petites lignes de code vous font peur ?
  • wiskywisky Membre
    17:29 modifié #16
    dans 1124461394:

    Hé bé vos codes m'ont l'air bien compliqués !
    (Et Eddy, pourquoi ne pas utiliser NSMakeSize et NSMakeRect ? enfin bref)

    Mes 3 petites lignes de code vous font peur ?

    non même pas peur ;)

    centrer une image en plus de 3 lignes c'est de l'abu (je me prend pour qui là ?)

    je connaà®t bien RB mais il me saoul avec ses bug et limitation à  la con. au moins en cocoa no limit ;)
  • Eddy58Eddy58 Membre
    17:29 modifié #17
    dans 1124461394:

    Hé bé vos codes m'ont l'air bien compliqués !
    (Et Eddy, pourquoi ne pas utiliser NSMakeSize et NSMakeRect ? enfin bref)

    C'est un code que j'ai fait à  mes débuts en Cocoa...il doit avoir pas loin de trois ans...pleins de trucs que je connaissais pas à  cette époque, il a le mérite de marcher même si côté optimisation c'est pas ça. ;)
Connectez-vous ou Inscrivez-vous pour répondre.