La rotation en .NET avec les fichiers JPEG perte de qualité minimale

voix
6

Je cherche à soutenir des images JPEG en rotation à partir de ASP.NET MVC (par incréments de 90 degrés). Je cherche à utiliser System.Drawing(GDI +), mais je suis en cours d' exécution sur les questions.

J'ai essayé d' utiliser ce Image.RotateFlipqui est capable de faire pivoter l'image , mais provoque une perte de qualité. Même avec une qualité de l' encodeur de 100, il y a encore des artefacts visibles sur l'image pivotée qui n'étaient pas sur l'image originale et ils ne montrent quand je tourne à l'aide d' autres programmes (ganse, etc.).

using (Image image = Image.FromFile(C:\\source.jpg)) {
    ImageFormat sourceFormat = image.RawFormat;
    image.RotateFlip(RotateFlipType.Rotate90FlipNone);
    EncoderParameters encoderParams = null;
    try {
        if (sourceFormat == ImageFormat.Jpeg) {
            encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
        }
        image.Save(C:\\target.jpg, GetEncoder(sourceFormat), encoderParams);
    } finally {
        if (encoderParams != null)
            encoderParams.Dispose();
    }
}

J'ai trouvé un article sur la transformation d' un JPEG sans perte d'information . L' utilisation Encoder.Transformationsemble être une option dans .NET - mais je ne peux pas le faire pour causer une de mes images de test JPEG pour tourner à tout, si les dimensions sont ou non un multiple de 16.

using (Image image = Image.FromFile(C:\\source.jpg)) {
    ImageFormat sourceFormat = image.RawFormat;
    EncoderParameters encoderParams = null;
    try {
        if (sourceFormat == ImageFormat.Jpeg) {
            encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Transformation, 
                (long)EncoderValue.TransformRotate90);
        }
        image.Save(C:\\target.jpg, GetEncoder(sourceFormat), encoderParams);
    } finally {
        if (encoderParams != null)
            encoderParams.Dispose();
    }
}

Est-ce que quelqu'un sait comment faire tourner avec succès un JPEG en .NET par incréments de 90 degrés avec une perte minimale ou pas de qualité en utilisant l'une des méthodes ci-dessus ou d'une autre méthode? Merci.

, Voici aussi ma mise en œuvre GetEncoder:

private ImageCodecInfo GetEncoder(ImageFormat format) {
    foreach (var info in ImageCodecInfo.GetImageEncoders())
        if (info.FormatID == format.Guid)
            return info;
    return null;
}

Modifier:

Je mis à jour le code ci-dessus pour mieux correspondre à mon code actuel. Le bogue a été dans la ligne suivante:

if (sourceFormat == ImageFormat.Jpeg) {

Il aurait dû être:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) {
Créé 27/07/2009 à 07:27
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
2

Avec une méthode qui décompresse l'image, tourne et le comprime, vous obtiendrez une perte de qualité.

Le format JPEG compresse les informations de couleur en carrés de 2x2 pixels en obtenant une couleur moyenne pour représenter les quatre pixels, donc si votre largeur de l'image et la hauteur sont divisible par deux, vous perdrez moins de qualité que la plupart des renseignements supprimés dans la compression est des informations a été interpolée de la décompression.

De même l'information de luminosité est compressé en carrés de 8x8 pixels, donc si votre largeur et hauteur sont par huit divisible, la grille s'alignera après la rotation de l'image et vous perdrez moins d'informations réelles.

Pour faire une rotation sans perte, vous devez utiliser une méthode complètement différente, la lecture du fichier JPEG et réorganisant et en rotation chaque carré de l'information de manière à former l'image pivotée sans décompresser et recompresser il.

Créé 27/07/2009 à 08:31
source utilisateur

voix
1

Merci de confirmer que mon code affiché travaillé. Cela m'a aidé à isoler mon problème. Je me sens stupide maintenant. Mon code actuel avait un chèque de format d'image avant de encoderParams- mais il y avait un bug:

if (sourceFormat == ImageFormat.Jpeg) {
    // set encoderParams here

J'ai découvert le conditionnel ci - dessus était toujours faux alors encoderParamsn'était pas réglée. La solution était simple:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) {
Créé 27/07/2009 à 08:17
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more