2009-08-31 13 views
15

J'ai écrit un service Web pour redimensionner les images téléchargées par l'utilisateur et tout fonctionne correctement d'un point de vue fonctionnel, mais l'utilisation du processeur augmente chaque fois qu'il est utilisé. Il fonctionne sur Windows Server 2008 64 bits. J'ai essayé de compiler à 32 et 64 bits et obtenir à peu près les mêmes résultats.Efficacité de redimensionnement de l'image en C# et .NET 3.5

Le cœur du service est cette fonction:

private Image CreateReducedImage(Image imgOrig, Size NewSize) 
{ 
    var newBM = new Bitmap(NewSize.Width, NewSize.Height); 
    using (var newGrapics = Graphics.FromImage(newBM)) 
    { 
     newGrapics.CompositingQuality = CompositingQuality.HighSpeed; 
     newGrapics.SmoothingMode = SmoothingMode.HighSpeed; 
     newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
     newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, NewSize.Width, NewSize.Height)); 
    } 

    return newBM; 
} 

Je mets un profileur sur le service et il semble indiquer que la grande majorité du temps est consacré à la bibliothèque GDI + lui-même et il n'y a pas grand-chose à gagner dans mon code. Est-ce que je fais quelque chose de manifestement inefficace dans mon code ici? Il semble se conformer à l'exemple que j'ai vu.

Y a-t-il des avantages à utiliser des bibliothèques autres que GDI +? Les benchmarks que j'ai vus semblent indiquer que GDI + se compare bien à d'autres bibliothèques mais je n'en ai pas trouvé assez pour être confiant.

Y a-t-il des avantages à utiliser des blocs "code non sécurisé"? S'il vous plaît laissez-moi savoir si je n'ai pas inclus assez du code ... Je suis heureux de mettre autant que demandé, mais ne veulent pas être désagréable dans le poste.

+0

Si vous exécutez ceci dans une boucle serrée, combien d'images/sec pouvez-vous traiter à quelles tailles d'image d'entrée/sortie? –

+0

Si je cours seulement la partie de redimensionnement d'image du code, je peux redimensionner 1000 images en 45 secondes environ. Entrée 873x655 et redimensionnée et recadrée à 300x250. –

+0

Quelque chose ne va pas. La bibliothèque [ImageResizer pour ASP.NET] (http://imageresizing.net) utilise GDI + en interne et a * beaucoup * de débit plus élevé. Je suppose que cela est dû à la façon dont les E/S sont gérées - mettre en mémoire tampon le flux de fichiers en mémoire avant de créer une instance Image/Bitmap élimine certaines failles de concurrence. –

Répondre

6

Le traitement d'image est généralement une opération coûteuse. Vous devez vous rappeler qu'une image couleur de 32 bits est agrandie dans la mémoire en largeur de pixel * 4 * avant que votre application ne commence à traiter. Un pic est certainement à prévoir surtout quand vous faites n'importe quel type de traitement de pixel. Cela dit, le seul endroit où je pourrais vous voir pour accélérer le processus ou réduire l'impact sur votre processeur est d'essayer un mode d'interpolation de qualité inférieure.

3

Je sais que le DirectX publié avec Windows 7 est censé fournir une accélération matérielle 2D. Si cela implique qu'il va battre GDI + sur ce genre d'opération, je ne sais pas. MS a une description assez flatteuse de GDI here qui implique qu'il est plus lent que cela devrait être, entre autres choses.

Si vous voulez vraiment essayer de faire ce genre de choses vous-même, il y a un bon GDI Tutorial qui le montre. L'auteur utilise à la fois SetPixel et "blocs dangereux", dans différentes parties de ses tutoriels. En outre, le multi-threading vous aidera probablement ici, en supposant que votre serveur a plus d'un CPU. Autrement dit, vous pouvez traiter plus d'une image à la fois et obtenir probablement des résultats plus rapides.

2

Vous pouvez essayer

newGrapics.InterpolationMode = InterpolationMode.Low; 

comme HighQualityBicubic sera le plus processeur intensif des opérations de ré-échantillonnage, mais bien sûr, vous perdrez alors la qualité de l'image. En dehors de cela, je ne vois vraiment rien qui puisse être fait pour accélérer votre code. GDI + sera certainement le plus rapide sur une machine Windows (aucun code écrit en C# ne dépassera une simple bibliothèque C), et l'utilisation d'autres bibliothèques d'images comporte le risque potentiel de unsafe et/ou de code bogué. En résumé, le redimensionnement d'une image est une opération coûteuse, peu importe ce que vous faites.La solution la plus simple est de remplacer le processeur de votre serveur par un modèle plus rapide.

0

Je soupçonne que le pic est parce que vous avez le mode d'interpolation coudé. Tous les modes d'interpolation fonctionnent par pixel et BiCubic High Quality est à peu près aussi haut que vous pouvez aller avec GDI +, donc je pense que les calculs par pixel sont en train de mâcher votre CPU.
En tant que test, essayez de passer le mode d'interpolation à InterpolationModeNearestNeighbor et de voir si le pic du processeur diminue - si c'est le cas, alors c'est votre coupable.
Si oui, alors faire quelques essais et erreurs pour le coût vs qualité, les chances sont que vous ne pourriez pas besoin de haute qualité BICUBIC pour obtenir des résultats décents

2

Lorsque vous écrivez

J'ai écrit un service Web pour redimensionner images téléchargées par l'utilisateur

Il me semble que l'utilisateur télécharge une image sur un serveur (Web?) et que le serveur appelle un service Web pour effectuer la mise à l'échelle?

Si c'est le cas, je déplacerais simplement la mise à l'échelle directement sur le serveur. Imho, la mise à l'échelle d'une image ne justifie pas son propre service Web. Et vous obtenez un trafic un peu inutile allant du serveur au service Web, et vice versa. En particulier parce que l'image est probablement encodée en base64, ce qui rend le trafic de données encore plus important.

Mais je ne fais que deviner ici.

p.s. Les blocs dangereux en eux-mêmes ne donnent aucun gain, ils permettent simplement de compiler du code dangereux. Donc, sauf si vous écrivez votre propre routage de mise à l'échelle, un bloc dangereux ne va pas aider.

2

Vous pouvez essayer ImageMagick. C'est gratuit, et il y a aussi un wrapper .NET: click here. Ou here. Ou vous pouvez envoyer une commande à un shell DOS.

Nous avons utilisé ImageMagick sur Windows Servers de temps en temps, pour le traitement par lots et parfois pour une conversion d'image plus flexible.

Bien sûr, il existe aussi des composants commerciaux, comme ceux de Leadtools et Atalasoft. Nous n'avons jamais essayé ceux-là.