Enregistrement du contenu UIView dans iOS 4 avec la taille réelle des images à l'intérieur (à savoir l'échelle contentes pour sauver)

StackOverflow https://stackoverflow.com/questions/4213529

Question

J'ai un UIView avec beaucoup UIImageViews comme subviews. L'application fonctionne sur iOS4 et j'utiliser des images avec une résolution d'affichage de la rétine (à savoir les images à charger échelle = 2)

Je veux enregistrer le contenu du UIView ... MAIS ... ont la taille réelle des images à l'intérieur. C'est à dire. la vue a la taille 200x200 et des images avec échelle = 2 à l'intérieur, je voudrais enregistrer une image résultante de 400x400 et toutes les images avec leur taille réelle.

Maintenant, ce qui vient d'abord à l'esprit est de créer un nouveau contexte d'image et charger à nouveau toutes les images à l'intérieur avec échelle = 1 et qui devrait le faire, mais je me demandais s'il y a une façon de faire plus élégante? On dirait une taille de temps de mémoire et le processeur de recharger à nouveau tout, car il est déjà fait ...

p.s. si quelqu'un a une réponse - y compris le code serait bien

Était-ce utile?

La solution

La mise en œuvre pour le rendu tout UIView à l'image (travaille également pour l'affichage de la rétine).

fichier helper.h:

@interface UIView (Ext) 
- (UIImage*) renderToImage;
@end

et d'appartenance mise en œuvre dans le fichier helper.m:

#import <QuartzCore/QuartzCore.h>

@implementation UIView (Ext)
- (UIImage*) renderToImage
{
  // IMPORTANT: using weak link on UIKit
  if(UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
  } else {
    UIGraphicsBeginImageContext(self.frame.size);
  }

  [self.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();  
  return image;
}

0,0 est le facteur d'échelle. Le facteur d'échelle à appliquer au bitmap. Si vous spécifiez une valeur de 0,0, le facteur d'échelle est réglé sur le facteur d'échelle de l'écran principal de l'appareil.

QuartzCore.framework devrait également être mis dans le projet parce que nous appelons la fonction de l'objet de la couche.

Pour activer maillon faible sur le cadre UIKit, cliquez sur l'élément de projet dans le navigateur gauche, cliquez sur la cible du projet -> construire des phases -> lien binaire et choisissez « option » (faible) type sur le cadre UIKit

.

Voici avec des extensions similaires pour UIColor, UIImage, NSArray, NSDictionary, ...

Autres conseils

J'ai effectué une telle chose pour sauver les broches de la MKMapView comme un fichier PNG (dans l'affichage rétine): MKPinAnnotationView: y at-il plus de trois couleurs disponibles

?

Voici un extrait de la partie cruciale qui effectue la sauvegarde d'un UIView (theView) en utilisant la définition de la rétine:


-(void) saveMyView:(UIView*)theView {
    //The image where the view content is going to be saved.
    UIImage* image = nil;
    UIGraphicsBeginImageContextWithOptions(theView.frame.size, NO, 2.0);
    [theView.layer renderInContext: UIGraphicsGetCurrentContext()];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData* imgData = UIImagePNGRepresentation(image);
    NSString* targetPath = [NSString stringWithFormat:@"%@/%@", [self writablePath], @"thisismyview.png" ];
    [imgData writeToFile:targetPath atomically:YES]; 
}

-(NSString*) writablePath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; return documentsDirectory; }

La clé est que le troisième paramètre à UIGraphicsBeginImageContextWithOptions est échelle , qui détermine comment l'image sera en fin de compte être écrit.

Si vous voulez toujours les dimensions réelles de pixels, utilisez [échelle [UIScreen mainScreen]] pour obtenir l'échelle actuelle de l'écran:

UIGraphicsBeginImageContextWithOptions(viewSizeInPoints, YES, [[UIScreen mainScreen] scale]);

Si vous utilisez l'échelle = 1.0 sur iPhone4, vous obtiendrez une image avec sa dimension dans Points et le résultat est réduite du nombre de pixels vrai. Si vous écrivez manuellement l'image vers une 640x960 dimension (par exemple: pixels en passant comme premier paramètre), il sera en fait l'image à échelle réduite qui est revu à la baisse en ce qui semble à peu près aussi terrible que vous l'imaginez regarderait

Pourriez-vous pas créer simplement un nouveau contexte graphique à la taille désirée, utilisez un CGAffineTransform à l'échelle vers le bas, rendre la couche racine de UIView racine, restaurer le contexte de la taille d'origine et de rendre l'image? Je n'ai pas essayé pour le contenu rétine, mais cela semble bien fonctionner pour les grandes images qui ont été mis à l'échelle dans UIImageViews ...

quelque chose comme:

CGSize originalSize = myOriginalImage.size; //or whatever

//create context
UIGraphicsBeginImageContext(originalSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); //1 original context

// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, originalSize.height);
CGContextScaleCTM(context, 1.0, -1.0);

//original image
CGContextDrawImage(context, CGRectMake(0,0,originalSize.width,originalSize.height), myOriginalImage.CGImage);

CGContextRestoreGState(context);//1 restore to original for UIView render;

//scaling
CGFloat wratio = originalSize.width/self.view.frame.size.width;
CGFloat hratio = originalSize.height/self.view.frame.size.height;

//scale context to match view size
CGContextSaveGState(context); //1 pre-scaled size
CGContextScaleCTM(context, wratio, hratio);

//render 
[self.view.layer renderInContext:context];

CGContextRestoreGState(context);//1  restore to pre-scaled size;

UIImage *exportImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Importer QuartzCore (Cliquez sur le projet principal, Construire des phases, l'importation) et où vous en avez besoin ajouter:

#import <QuartzCore/QuartzCore.h>

Mes imageViews sont des propriétés, si vous n'êtes pas, ignorer le .self et passer la imageViews dans la fonction en tant que paramètres, puis appelez renderInContext sur les deux images dans une nouvelle UIGraphicsCurrentContext

- (UIImage *)saveImage
{
    UIGraphicsBeginImageContextWithOptions(self.mainImage.bounds.size, NO, 0.0);

    [self.backgroundImage.layer renderInContext:UIGraphicsGetCurrentContext()];
    [self.mainImage.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *savedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return savedImage;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top