2016-08-05 8 views
2

J'utilise une classe personnalisée pour écrire une image sur une autre image de plus grande taille. Voici le plein source code dans DotNetFiddle.Dessiner un bitmap sur un autre produit une image déformée

Ma personnalisation GetPixel() fonctionne correctement. Mais le SetPixel() suivant est incapable de produire la sortie appropriée. Probablement, il y a eu quelques problèmes avec le calcul des adresses. Mais, je suis incapable de le détecter.

public void SetPixel(int x, int y, Color color) 
    { 
     // Get color components count 
     int cCount = ColorDepth/8; 
     // Get start index of the specified pixel 
     int i = ((y * Width) + x) * cCount; 
     //int i = ((x * Width) + y) * cCount; 
     if (ColorDepth == 32) // For 32 bpp set Red, Green, Blue and Alpha 
     { 
      _imageData[i] = color.B; 
      _imageData[i + 1] = color.G; 
      _imageData[i + 2] = color.R; 
      _imageData[i + 3] = color.A; 
     } 

     if (ColorDepth == 24) // For 24 bpp set Red, Green and Blue 
     { 
      _imageData[i] = color.B; 
      _imageData[i + 1] = color.G; 
      _imageData[i + 2] = color.R; 
     } 
     if (ColorDepth == 8) 
     { 
      // For 8 bpp set color value (Red, Green and Blue values are the same) 
      _imageData[i] = color.B; 

      string str = string.Empty; 
     } 
    } 

C'est génère une image déformée:

enter image description here

.

P.S. Voici l'image d'entrée:

enter image description here

.

.

+0

"Indice hors limites" est l'indice que vous obtenez. Il se réfère à '_imageData [i]' et n'a rien à voir avec les pixels Get/Set, sauf qu'il y a un bug dans le code. Puisque le débogueur est déjà actif, prenez le temps d'inspecter la valeur de 'i' et la taille de' _imageData'. – user2864740

+0

Notez également que '(x * Q) + y' ne peut pas être inversé à l'aveugle en tant que' (y * Q) + x' (ils se traduiront par une plage différente), quand 'y! = X'. – user2864740

+0

Essayez de redimensionner l'image en conservant le rapport d'aspect: http://stackoverflow.com/questions/1940581/c-sharp-image-resizing-to-different-size-while-preserving-aspect-ratio –

Répondre

2
// Get start index of the specified pixel 
    int i = ((y * Width) + x) * cCount; 

Cela n'est pas correct, ni dans GetPixel ni dans SetPixel. Vous obtenez le biais parce que vous ignorez Stride. Quels sont le nombre d'octets dans une seule ligne de balayage de l'image. C'est un multiple de 4 à aligner les données de pixel dans la mémoire, aide le processeur à lire les données plus rapidement. Correction:

int i = y * Stride + x * cCount; 

Un autre bogue est caché dans votre code, les lignes de balayage sont stockées à l'envers. En d'autres termes, les données de la dernière ligne de balayage sont stockées en premier. Mais seulement si BitmapData.Height n'est pas négatif. Puisque ce bug se produit à la fois dans vos méthodes GetPixel et SetPixel, ils s'annulent mutuellement. Le code correct serait (Hauteur - y - 1) * Stride + x * cCount.

Ce code n'est pas plus rapide que Graphics.DrawImage(), la méthode que vous devriez toujours préférer.

+0

Veuillez utiliser les informations fournies pour conclure que vous n'avez pas créé le tableau correctement. Même erreur, vous utilisez à nouveau Width au lieu de Stride. –

+0

Cher Hans, s'il vous plaît voir le lien. J'ai utilisé '(Height - y - 1) * Stride + x * cCount'. http://i.imgur.com/MBfMvVh.png – anonymous

+1

Non, le problème est votre tableau '_imageData' **, il doit bien sûr contenir les octets Stride * Height pour stocker tout le bitmap. Vous ne le faites pas assez grand. –