Frage

Bei einem UIImage jeder Dimension, wünsche ich ein Quadrat „Symbol“ Größe Version, px Pixel auf eine Seite zu erzeugen, ohne jede Verzerrung (Dehnung). Aber ich bin mit in einen kleinen Haken. Nicht ganz sicher, wo das Problem ist. Hier ist, was ich bisher zu tun.

Zuerst gegeben ein uImage size, bestimme ich drei Dinge: die ratio zu verwenden, wenn das Bild Verkleinerung; a delta (der Unterschied zwischen unserer gewünschten Icon-Größe und der längsten Seite) und eine offset (die unsere Ursprungskoordinate herauszufinden verwendet wird, wenn der Bildausschnitt):

 if (size.width > size.height) {
   ratio = px / size.width;
   delta = (ratio*size.width - ratio*size.height);
   offset = CGPointMake(delta/2, 0);
 } else {
   ratio = px / size.height;
   delta = (ratio*size.height - ratio*size.width);
   offset = CGPointMake(0, delta/2);
 }

Nun lassen Sie uns sagen, Sie haben ein Bild 640px breit und 480px hoch, und wir wollen aus dieser einen 50px x 50px Symbol erhalten. Die Breite ist größer als die Höhe, so dass unsere Berechnungen sind:

ratio = 50px / 640px = 0.078125
delta = (ratio * 640px) - (ratio * 480px) = 50px - 37.5px = 12.5px
offset = {x=6.25, y=0}

Als nächstes erstelle ich ein CGRect rect, die groß genug ist, um unsere gewünschte Symbolgröße zu werden abgeschnitten unten ohne Verzerrung sowie eine clipRect für Zwecke Clipping:

CGRect rect = CGRectMake(0.0, 0.0, (ratio * size.width) + delta,
                                   (ratio * size.height) + delta);
CGRect clipRect = CGRectMake(offset.x, offset.y, px, px);

unsere Werte von oben Substituieren, erhalten wir:

rect = origin {x=0.0, y=0.0}, size {width=62.5, height=50.0}
clipRect = origin {x=6.25, y=0}, size {width=50.0, height=50.0}

So, jetzt haben wir eine 62.5px breit und 50px hoch rect mit zu arbeiten, und ein Clipping-Rechteck, das die „Mitte“ 50x50 Teil greift.

Auf zum Endspurt! Als nächstes stellen wir unser Bild Kontext auf, die ziehen UIImage in den rect, setzen Sie das Clipping-Rechteck, erhalten die (vermutlich jetzt geschoren) Bild (myImage hier genannt wird), sie verwenden und schließlich aufzuräumen unser Bild Kontext:

 UIGraphicsBeginImageContext(rect.size);
 [myImage drawInRect:rect]; 
 UIRectClip(clipRect);
 UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();

 // Do something with the icon here ...

 UIGraphicsEndImageContext();

Nur ein Problem: Das Clipping nie auftritt! Ich beende breit mit einem Bild 63px bis x 50px hoch. :(

Vielleicht bin ich zu mißbrauchen / Mißverständnis UIRectClip ? Ich habe versucht, verschiedene Dinge herumschlurfenden: die Verwendung von rect und clipRect Swapping, bewegen UIRectClip vor drawInRect: . Keine Würfel.

Ich habe versucht, für ein Beispiel dieser Methode suchen auch online, ohne Erfolg. Für die Aufzeichnung UIRectClip ist wie folgt definiert:

  

ändert den aktuellen Beschneidungspfad durch   ich schneid es mit dem angegebenen   Rechteck.

Shuffling Dinge um bringt uns ein wenig näher:

UIGraphicsBeginImageContext(clipRect.size);
UIRectClip(rect);
[myImage drawInRect:rect];

Jetzt haben wir Verzerrung nicht, aber das beschnittene Bild wird nicht auf dem ursprünglichen zentriert ist, wie ich erwartet hatte. Dennoch ist zumindest das Bild 50x50, obwohl die Variablennamen nun als Folge der schlurfenden verschmutzt sind. (Ich werde respektvoll als eine Übung für die Leser überlassen Umbenennung.)

War es hilfreich?

Lösung

Eureka! Ich hatte die Dinge ein wenig durcheinander. Dies funktioniert:

CGRect clipRect = CGRectMake(-offset.x, -offset.y,
                             (ratio * size.width) + delta,
                             (ratio * size.height) + delta);
UIGraphicsBeginImageContext(CGSizeMake(px, px));
UIRectClip(clipRect);
[myImage drawInRect:clipRect];
UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();

// Do something with the icon here ...

UIGraphicsEndImageContext();

Keine Notwendigkeit mehr für rect. Der Trick scheint zu sein mit a negativ in dem Clipping-Rechteck versetzt, wodurch Schlange, den Ursprungs, wo wir wollen, dass unser 50 x 50 Bild greifen (in diesem Beispiel).

Vielleicht gibt es einen einfacheren Weg. Wenn ja, wiegen Sie sich bitte an!

Andere Tipps

Ich wollte etwas ähnliches erreichen, aber fand die Antwort aus durch das ursprüngliche Plakat nicht ganz die Arbeit. Es verzerrt das Bild. Dies kann gut allein sein, weil er nicht die ganze Lösung hat Post und hatte einige, wie die Variablen initialisiert geändert:

 (if (size.width > size.height) 
       ratio = px / size.width;

falsch war für meine Lösung (die ein möglichst großes Quadrat aus dem Quellbild verwenden wollte). Auch ist es nicht erforderlich, UIClipRect zu verwenden - wenn Sie den Kontext der Größe des Bildes entnehmende machen, keine tatsächlichen Zeichnung wird außerhalb dieses rect ohnehin durchgeführt werden. Es ist nur eine Frage der Größe des Bildes rect Skalierung und einer der Ursprungskoordinaten zu kompensieren. Ich habe meine Lösung unten geschrieben:

+(UIImage *)makeIconImage:(UIImage *)image
{
    CGFloat destSize = 400.0;
    CGRect rect = CGRectMake(0, 0, destSize, destSize);

    UIGraphicsBeginImageContext(rect.size);

    if(image.size.width != image.size.height)
    {
        CGFloat ratio;
        CGRect destRect;

        if (image.size.width > image.size.height)
        {
            ratio = destSize / image.size.height;

            CGFloat destWidth = image.size.width * ratio;
            CGFloat destX = (destWidth - destSize) / 2.0;

            destRect = CGRectMake(-destX, 0, destWidth, destSize);

        }
        else
        {
            ratio = destSize / image.size.width;

            CGFloat destHeight = image.size.height * ratio;
            CGFloat destY = (destHeight - destSize) / 2.0;

            destRect = CGRectMake(0, destY, destSize, destHeight);
        }
        [image drawInRect:destRect];
    }
    else
    {
        [image drawInRect:rect];
    }
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledImage;
}

wheeliebin Antworten ist richtig, aber er vergaß, ein Minuszeichen vor destY

destRect = CGRectMake(0, -destY, destSize, destHeight);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top