Comment réduire la résolution d'une UIImage dans IOS par la taille des Données
Je suis à la recherche pour convertir un UIImage
dans iOS
.
J'ai vu d'autres questions ci-dessous et leur approche sur la façon de réduire la taille de l'image par la taille.
Le Redimensionnement D'Images Objective-C
Comment redimensionner l'image par programmation en objective-c dans l'iphone
La façon la plus simple pour redimensionner une UIImage?
Ces questions sont toutes basées sur le changement de la taille de l'image à une taille spécifique. Dans mon cas, je suis à la recherche de re-taille/réduire la taille de l'image basée sur une taille maximale.
Comme un exemple, je voudrais mettre un maximum NSData
taille de 500 KO. Je sais que je peux obtenir la taille de l'image comme ceci://Vérifier la taille de l'image renvoyée
NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
//Log out the image size
NSLog(@"%lu KB",(imageData.length/1024));
Ce que j'aimerais faire, c'est une certaine forme de boucle ici. Si la taille est supérieure à la taille maximale que j'ai mis, je tiens à l'échelle de l'image légèrement, puis vérifier la taille. Si la taille est trop grande échelle vers le bas à nouveau légèrement, puis vérifier de nouveau, jusqu'à ce qu'il est inférieur au maximum de la taille de l'ensemble.
Je ne suis pas sûr de ce que la meilleure approche pour ce qui est. Idéalement, je ne veux pas l'échelle vers le bas de l'image à une taille précise, tout le temps, mais seulement légèrement vers le bas l'échelle de l'image à chaque fois. De cette façon, je peux avoir le plus grand (taille l/h) de l'image elle-même et à sa taille maximale (en octets). Si je échelle légèrement à la baisse qu'à une époque, quelle serait la meilleure façon d'accomplir cette?
MODIFIER
Pour confirmer, je suis à la recherche de re-taille de l'image réelle, mais ré-taille de l'image, de sorte qu'il est plus petit que le maximum de NSData
Longueur.
Par exemple:
-Vérifier la NSData
Longueur
-Si au-dessus du maximum que j'ai envie de passer à la UIImage dans une méthode
-Ensuite une boucle au travers de cette méthode légèrement re-dimensionnement de la taille réelle de l'image à chaque fois
-Jusqu'à ce qu'il est sous le maximum NSData
longueur, puis retourner l'image?
UIImage
objet? (Dans ce scénario, la compression JPEG options ne sont pas vraiment pertinents, tout résultant en la perte de la qualité de l'image sans affecter la quantité de mémoire utilisée.)Je suis en train de faire ce pour des restrictions de téléchargement. Je voudrais à l'échelle de la taille de l'image, par opposition à la compression à maintenir la qualité de. Au moment de l'utilisation de la mémoire n'est pas un problème.
Ok, alors vous pouvez ne pas tenir compte de ma réponse, mais je vais l'y maintenir pour les futurs lecteurs.
La réponse ici: stackoverflow.com/q/20458558/2057171
OriginalL'auteur StuartM | 2013-12-05
Vous devez vous connecter pour publier un commentaire.
Droit maintenant, vous avez une routine qui dit:
Je ne le conseille pas récursivement le redimensionnement de l'image. Chaque fois que vous redimensionnez, vous perdez une partie de la qualité (souvent manifeste lui-même comme un "adoucissement" de l'image, avec une perte de détails, avec des effets cumulatifs). On a toujours envie de revenir en arrière à l'original de l'image et la redimensionner, que de plus en plus petites. (Comme un mineur de côté, que
if
déclaration est redondant, trop.)Je pourrais suggérer le suivant:
Remarque, je ne suis pas toucher
image
, l'image d'origine, mais plutôt l'attributioncurrentImage
en faisant un redimensionnement de l'image d'origine à chaque fois, par une diminution de l'échelle à chaque fois.BTW, si vous vous demandez à propos de mon cryptique
1.0 /sqrt(2.0)
, j'ai essayé de dessiner un compromis entre votre itératif facteur de 80% et mon désir de favoriser le redimensionnement par une puissance de 2 où je peux (car une réduction conserve plus de netteté quand c'est fait par une puissance de 2). Mais quelle que soit l'utilisationadjustment
facteur que vous voulez.Enfin, si vous êtes en train de faire cela sur des images énormes, vous pouvez penser à l'aide de
@autoreleasepool
blocs. Vous aurez envie de profil de votre application dans les Affectations dans les Instruments et de voir où votre marque des hautes eaux est, comme en l'absence d'autorelease piscines, ce qui peut constituer une assez agressif utilisation de la mémoire.qu'est-ce que kMESImageQuality?
Autant que je sache, ce n'est un peu aléatoire constante qui StuartM défini (que j'ai ensuite fidèlement copiés dans ma réponse). Vous verrez qu'il est référencé dans d'autres questions par lui (voir stackoverflow.com/q/20483242/1271826, par exemple). Il n'est pas vraiment pertinent ici. Utiliser ce que vous voulez. Personnellement, lorsque vous faites Jpeg, je vais utiliser des valeurs entre 0,7 et 0,9, qui offrent décent de compression, mais sans détruire la qualité de l'image trop. Et si je ne veux pas de présenter une perte d'image, je vais utiliser le format PNG représentations (qui n'offrent qu'un peu de compression, mais c'est sans perte et plus petit que le format JPEG avec une qualité de 1.0).
OriginalL'auteur Rob
En plus de la taille maximale que vous avez aussi besoin de choisir une taille minimale ainsi que de décider sur les performances. Par exemple, vous pouvez vérifier la taille de
UIImageJPEGRepresentation(image, 1.0)
. Si trop gros, ne vous vérifiez ensuite à0.95
ou0.1
?Une approche possible est d'obtenir la taille de
UIImageJPEGRepresentation(image, 1.0)
et de voir par quel pourcentage il est trop grand. Par exemple, dire que c'est 600 ko. Vous devez ensuite calculer500.0 /600
qui est à peu près0.83
. Alors neUIImageJPEGRepresentation(image, 0.83)
. Que ne lui donnera pas exactement 500kB mais il peut être assez proche.Une autre approche serait de commencer avec
UIImageJPEGRepresentation(image, 1.0)
. C'est trop gros alors neUIImageJPEGRepresentation(image, 0.5)
Si trop gros puis aller avec0.25
mais si c'est trop petit aller avec0.75
. Garder le fractionnement de la différence jusqu'à ce que vous obtenez à l'intérieur d'une fourchette acceptable à la taille désirée.Votre question n'était pas claire. Vous avez parlé de toutes les re-dimensionnement des questions n'étant pas ce que tu voulais, et en se basant sur la taille du fichier. De toute façon, ce serait la même approche de base. Au lieu de régler la qualité de l', ajuster la taille de l'image. Commencer à 1024 x 768 (par exemple). Ajuster cette taille en fonction de combien vous avez besoin pour réduire l'image.
Toutes mes excuses je n'ai pas été clair sur l'explication. Je voulais dire que je n'essaie pas de changer directement à une taille spécifique, cependant, je voudrais modifier la taille de l'image à la une incidence sur la taille. Donc, si l'image est 1024KB en taille (NSData Longueur) je veux re-taille de l'image qui aurait une incidence sur la taille. Plus précisément, je suis à la recherche de la meilleure façon de faire une boucle par la présente, je ne veux pas écrire un tas de if (re-taille), puis un autre re-taille. Mais plutôt de passer l'image en méthode, et de renvoyer une image qui est de la taille appropriée (NSData Longueur) peut vous aider avec cette approche?
J'ai ajouté un edit pour plus de clarté aussi
Le pourcentage de la méthode que vous avez décrit ci-dessus est une bonne approche. Je l'ai essayé et a été d'obtenir des valeurs beaucoup plus faibles que ma cible "taille maximale" si... alors ce que j'ai fait était de prendre le courant JPG-compression-paramètre-flotteur et le nouveau pourcentage multiplié float et la moyenne des deux, puis appliqués et réaffirmé dans une boucle while jusqu'à ce que j'ai obtenu mon taille du fichier cible. Habituellement ne me prend que 2-3 itérations pour atteindre une taille de fichier, qui est à environ 2% de marge d'erreur à ma cible "taille maximale", donc en limitant le montant de la perte de données. 🙂
OriginalL'auteur rmaddy
C'était mon approche:
Le redimensionnement de l'image de la méthode est comme suit:
Suivie par:
//Autres méthodes de référence
Très bon. BTW, je n'aurais pas de manière récursive redimensionner l'image. Chaque fois que vous redimensionnez, vous perdez une partie de la qualité (souvent manifeste lui-même comme un "adoucissement" de l'image, avec une perte de détails, avec des effets cumulatifs). On a toujours envie de revenir en arrière à l'original de l'image et la redimensionner, que de plus en plus petites. Et, si la netteté est important, je serais personnellement faire la première redimensionnement de la taille de 1/2, si elle est encore trop grande, alors 1/3 de la taille de l'original, s'il est encore trop gros 1/4 d'origine, etc. (puissances de 2 sont les meilleurs, en fait). Mais de manière récursive redimensionnement d'une image peut vraiment se dégrader de la netteté.
c'est un grand point dans le ci-dessus, je suis constamment à la modification de l'image contrairement à l'original lui-même. Ce qu'est une grande pensée, je vais mettre à jour ci-dessus...
Peut vous aider avec une approche de cette s'il vous plaît? Je ne vois pas comment réécrire mon scaleDown méthode (tout) à travailler avec une échelle vers le bas de l'image, par opposition à l'image d'origine. Je pense que je l'aurais pour le redimensionner à un ensemble spécifique de tous les temps, alors que j'espérais, je pourrait réduire de 80% à la fois pour la meilleure qualité. Je suis en train de remplir la même que ci-dessus, mais avec l'image d'origine à chaque fois.
Mis à jour avec cette méthode aussi. Merci
OriginalL'auteur StuartM
Il maintient la qualité de l'image pas lass de 1 MO.
Appeler avec,
OriginalL'auteur bharathi kumar
Dans votre nouvelle question, vous avez précisé que votre objectif est-à-dire dans les limitations de taille de fichier lors du téléchargement d'images. Dans ce cas, de jouer avec les options de compression JPEG est très bien comme suggéré par rmaddy.
La question intéressante est que vous avez deux variables de jouer avec, la compression JPEG et les dimensions de l'image (il y en a d'autres, trop, mais je vais faire simple). Comment voulez-vous mettre la priorité sur un sur l'autre? Par exemple, je ne pense pas qu'il est logique de garder une pleine résolution, par l'absurde image compressée (par exemple de 0,1 facteur de qualité). Ni est-il judicieux de garder une petite résolution, l'image non compressée. Personnellement, je serais de manière itérative ajuster la qualité comme suggéré par rmaddy, mais certaines raisonnable étage (par exemple, JPEG de qualité ne sont pas moins de, disons de 0,70). À ce point, je pourrais envisager de changer les dimensions de l'image (et que les changements de taille de fichier très vite, trop), et en modifiant les dimensions jusqu'à ce que le
NSData
était d'une taille appropriée.De toute façon, dans ma réponse originale à cette question, je me suis concentré sur la consommation de mémoire au sein de l'application (par opposition à la taille du fichier). Dans un souci de postérité, voir la réponse ci-dessous:
Si vous essayez de contrôler la quantité de mémoire est utilisée lorsque vous chargez les images dans
UIImage
objets à être utilisé dansUIKit
objets, puis de jouer avec la compression JPEG ne vous aidera pas beaucoup, parce que la représentation interne des images une fois que vous chargez dansUIKit
objets n'est pas compressé. Ainsi, dans ce scénario, la compression JPEG options de ne pas accomplir beaucoup (autres que de sacrifier la qualité d'image).Pour illustrer cette idée, j'ai une image qui est de 1920 x 1080. Je l'ai en format PNG (le fichier est 629kb), un comprimé le format JPEG (217kb), et un peu compressé au format JPEG (1.1 mo). Mais, lorsque je charge ces trois images différentes en
UIImageView
objets (même si ils ont un très petitframe
), de l'Instrument de "Dotations" outil me montre qu'ils sont chaque prise de 7.91 mb:C'est parce que lorsque vous chargez une image dans une image de la vue, de l'intérieur, non compressé, la représentation de ces trois images est de quatre octets par pixel (un octet pour le rouge, un pour le vert et un pour le bleu, et un pour l'alpha). Ainsi, un de mes 1920 x 1080 images prendre jusqu'à 1920 x 1080 x 4 = 8,249,400 = 7.91 mb.
Donc, si vous ne voulez pas qu'ils prennent plus de 500 ko en mémoire lors de leur chargement dans l'affichage de l'image des objets, ce qui signifie que vous souhaitez redimensionner, tels que le produit de la largeur de fois la hauteur sera de 128 000 ou moins (c'est à dire si square, moins de 358 x 358 pixels).
Mais, si votre préoccupation est l'un de la bande passante du réseau que vous télécharger des images ou persistante de la capacité de stockage, puis aller de l'avant et de jouer avec les valeurs de compression JPEG comme suggéré par rmaddy excellente réponse. Mais si vous êtes tenter de répondre à des problèmes de consommation de mémoire, tandis que les images sont chargées dans UIKit objets, alors ne mettez pas l'accent sur la compression, mais se concentrer sur le redimensionnement de l'image.
Compris. La question intéressante est que vous avez deux variables de jouer avec, la compression JPEG et les dimensions de l'image (il y en a d'autres, trop, mais je vais faire simple). Comment voulez-vous mettre la priorité sur un sur l'autre? Par exemple, je ne pense pas que c'est logique de le maintenir à un règlement complet, très compressé l'image (par exemple de 0,1 facteur). Ni est-il judicieux de garder une petite résolution, l'image non compressée. Personnellement, je serais une cible certaines raisonnable de compression qui ne se dégrade pas l'image trop (par exemple, 0.75), et ensuite modifier la taille jusqu'à ce que le
NSData
était d'une taille appropriée.Je suis complètement d'accord avec cette approche, je voudrais utiliser de 0,75 à la compression comme un point de base. Comme une sous-question, si je suis de passage d'une UIImage entre ViewControllers je suppose que ce passe toute la qualité de l'image, à moins que je fait passer le NSData pointeur à la place? Si je l'échelle de l'image à l'aide de NSData la compression de ce fait compresser le UIImage image?
Je ne suis pas entièrement sûr. J'ai été surpris, par exemple, que l'image créée par
imageNamed
etimageWithContentsOfFile
ne pas consommer beaucoup de mémoire jusqu'à ce que je l'ai utilisé dansUIImageView
. Cela me fait penser qu'il y a toutes sortes de sauvages optimisations passe en arrière-plan (et qui peuvent varier selon la version iOS). Mais pour répondre à votre question, je fais tout en mon pouvoir pour éviter de la transmettre autour deUIImage
objets (certainement jamais le maintien de tableaux deUIImage
objets). Si vous traitez avec beaucoup d'images, je vais le passent généralement autour d'un chemin d'accès vers le fichier plutôt que de l'image elle-même.Oui, mais cette montée de l'utilisation de la mémoire est éphémère et peut être limitée (par exemple, si le redimensionnement d'une douzaine de grandes images pour être présenté en vue de collection, le redimensionnement de routine peut les redimensionner en série, de sorte que le pic de l'utilisation de la mémoire est limitée à celle qui est requise par une seule grande image).
OriginalL'auteur Rob