Comment dois-je faire de haute qualité de mise à l'échelle d'une image?
Je suis en train d'écrire un peu de code pour mettre à l'échelle un 32 bits RGBA image en C/C++. J'ai écrit quelques tentatives qui ont connu un certain succès, mais ils sont lents, et surtout la qualité de la taille d'image n'est pas acceptable.
J'ai comparé la même image à l'échelle en OpenGL (c'est à dire ma carte vidéo) et ma routine et c'est miles de distance en qualité. J'ai Cherché sur Google Code, parcouru source arbres de ce que je pensais serait de jeter un peu de lumière (SDL, Allegro, wxWidgets, CxImage, GD, ImageMagick, etc.) mais généralement, leur code est alambiqué et dispersées au-dessus de l'endroit ou criblé avec l'assembleur et peu ou pas de commentaires. J'ai aussi lu plusieurs articles sur Wikipédia et ailleurs, et je ne suis pas à trouver une explication claire de ce dont j'ai besoin. Je comprends les concepts de base de l'interpolation et de l'échantillonnage, mais j'ai du mal à obtenir de l'algorithme de droit. Je ne veux PAS compter sur une bibliothèque externe pour l'un de routine et avoir à les convertir à leur format d'image et à l'arrière. D'ailleurs, j'aimerais savoir comment le faire moi-même de toute façon. 🙂
J'ai vu une question similaire posée sur un débordement de pile avant, mais ce n'était pas vraiment répondu de cette façon, mais je suis en espérant qu'il ya quelqu'un là-bas qui peut m'aider à déplacer dans la bonne direction. Peut-être m'indiquer certains des articles ou des pseudo-code... rien pour m'aider à apprendre et à faire.
Voici ce que je suis à la recherche de:
- Pas de l'assembleur (je suis en train d'écrire très portable code pour plusieurs types de processeurs).
- Pas de dépendances sur les bibliothèques externes.
- Je suis principalement concernée par la mise à l'échelle vers le BAS, mais aussi besoin d'écrire une échelle de routine plus tard.
- Qualité du résultat et la clarté de l'algorithme est le plus important (je peux l'optimiser plus tard).
Ma routine essentiellement prend la forme suivante:
DrawScaled(uint32 *src, uint32 *dst,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h );
Merci!
Mise à JOUR: Pour clarifier, j'ai besoin de quelque chose de plus avancé que d'une case rééchantillonnage pour désagrégation qui brouille l'image en trop. Je soupçonne ce que je veux, c'est une sorte de bicubique (ou d'autres) filtre qui est un peu l'inverse d'une interpolation bicubique algorithme (c'est à dire chaque destination pixel est calculée à partir de tous de contribuer pixels source combinée avec un algorithme de pondération qui empêche les choses de sharp.
Exemple
Voici un exemple de ce que je reçois de la wxWidgets BoxResample algorithme vs ce que je veux sur un 256x256 bitmap mis à l'échelle pour 55x55.
- www.free_image_hosting.net/uploads/1a25434e0b.png
Et enfin:
- www.free_image_hosting.net/uploads/eec3065e2f.png
l'origine de 256x256 pixels de l'image
- J'ai pris votre image source et de ré-appliquer la mise à l'échelle en utilisant wxWidgets pour obtenir le suivant freeimagehosting.net/image.php?128f096527.png Comme vous pouvez le voir, il n'est pas tout à fait aussi forte que l'OpenGL, mais c'est bien l'anti-aliasing et beaucoup plus nette que votre wx exemple.
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé la wxWidgets mise en œuvre assez simple de les modifier au besoin. C'est tout le C++ donc pas de problèmes avec la portabilité là. La seule différence est que leur mise en œuvre travaille avec des unsigned char tableaux (que je trouve être la façon la plus simple de traiter avec les images en tout cas) avec un ordre des octets de RVB et de la composante alpha dans un tableau séparé.
Si vous vous référez à l' "src/common/image.cpp" fichier dans le wxWidgets source de l'arbre il y a un bas-échantillonnage de la fonction qui utilise une boîte de méthode d'échantillonnage "wxImage::ResampleBox" et un scaler fonction appelée "wxImage::ResampleBicubic".
Assez simple et décent algorithme de rééchantillonnage des images est L'interpolation bicubique, wikipedia seul a toutes les informations dont vous avez besoin pour obtenir cette mise en œuvre.
Est-il possible que OpenGL est en train de faire la mise à l'échelle dans le vecteur de domaine? Si oui, il n'y a aucune manière que n'importe quel pixel de mise à l'échelle va être près de lui dans la qualité. C'est le gros avantage de vecteur basé des images.
Le bicubique algorithme peut être réglé pour la netteté vs artefacts - j'essaie de trouver un lien, je vais le modifier en quand je fais les.
Edit: C'était la Mitchell-Netravali travail que j'étais en train de penser, qui est référencé en bas de ce lien:
http://www.cg.tuwien.ac.at/~theussl/DA/node11.html
Vous pouvez également regarder dans Lanczos rééchantillonnage comme une alternative à la méthode bicubique.
Maintenant que je vois ton image d'origine, je pense que OpenGL est à l'aide d'un algorithme d'approximation. Non seulement est-il le plus simple possible pour redimensionner, mais c'est aussi le moyen le plus rapide. Le seul inconvénient, c'est qu'il a l'air très rugueuse si il y a un détail dans l'image d'origine.
L'idée est de prendre régulièrement espacés échantillons à partir de votre image d'origine; dans votre cas, 55 256, ou un de chaque 4.6545. Juste autour du nombre pour obtenir le pixel de choisir.
CodeProject articles de discussion et de partage de code source pour de mise à l'échelle des images:
Essayez d'utiliser le Adobe Image Générique de la Bibliothèque ( http://opensource.adobe.com/wiki/display/gil/Downloads ) si vous voulez quelque chose de prêt et non d'un algorithme.
Extrait de: http://www.catenary.com/howto/enlarge.html#c
D'agrandir ou de Réduire le Code Source C
Nécessite Victor Bibliothèque de Traitement d'Images pour Windows 32 bits v 5.3 ou supérieur.
Cet exemple permet de redimensionner une zone de l'image et remplace l'image d'origine avec la nouvelle image.
Intel a IPP bibliothèques qui offrent une forte interpolation de la vitesse des algorithmes optimisés pour les processeurs Intel de la famille de processeurs. C'est très bon mais il n'est pas gratuite mais. Jetez un oeil sur le lien suivant:
Intel IPP
Un article générique de notre cher hôte: Mieux Redimensionnement D'Image, de discuter des mérites relatifs des différents algorithmes (et des liens vers un autre CodeProject article).
Il semble que vous vous êtes vraiment à avoir de la difficulté à comprendre le discret -> continue -> discret flux impliqués dans correctement rééchantillonnage d'une image. Un bon tech rapport qui peut aider à vous donner un aperçu de ce que vous avez besoin est Alvy Ray Smith Un Pixel Est Pas Un Peu de Place.
Prendre un coup d'oeil à ImageMagick, qui fait toutes sortes de filtres de redimensionnement.
En suivi, Jeremy Rudd posté cet article ci-dessus. Il met en œuvre filtré deux passes de redimensionnement. Les sources sont en C#, mais il semble assez clair que je peux le porter à lui donner un essai. Je l'ai trouvé très semblable code C hier, ce fut beaucoup plus difficile à comprendre (très mauvais noms de variables). Je l'ai eu pour tri de travail, mais il était très lent et ne produisent pas de bons résultats, ce qui m'a amené à croire qu'il y avait une erreur dans mon adaptation. J'ai peut-être plus de chance écrit à partir de zéro avec une telle référence, je vais essayer.
Mais vu comment les deux pass algorithme fonctionne, je me demande si il n'y a pas un moyen plus rapide de le faire, peut-être même dans un pass?