2016-08-05 3 views
2

Я использую пользовательский класс для записи изображения на другое изображение большего размера. Вот полный source code в DotNetFiddle.Рисование растрового изображения на другое создает искаженное изображение

Мой заказ GetPixel() отлично работает. Но следующее SetPixel() не может произвести надлежащий вывод. Вероятно, были проблемы с расчетом адресов. Но я не могу это обнаружить.

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; 
     } 
    } 

Это порождает искаженное изображение:

enter image description here

.

P.S. Вот входное изображение:

enter image description here

.

.

+0

«Указатель вне диапазона» - это ключ, который вы получаете. Он ссылается на '_imageData [i]' и не имеет ничего общего с Get/Set pixels, за исключением того, что в коде есть ошибка. Поскольку отладчик уже активен, найдите время, чтобы проверить значение 'i' и размер' _imageData'. – user2864740

+0

Также обратите внимание, что '(x * Q) + y' не может быть слепо« перевернуто »как' (y * Q) + x' (они приведут к другому диапазону), когда 'y! = X'. – user2864740

+0

Попробуйте изменить размер изображения с сохранением Соотношение сторон: обзор http://stackoverflow.com/questions/1940581/c-sharp-image-resizing-to-different-size-while-preserving-aspect-ratio –

ответ

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

Это неверно, не в GetPixel и SetPixel. Вы получаете перекос, потому что игнорируете Stride. Какое количество байтов в одной строке сканирования изображения. Он кратно от 4 до выравнивает пиксельные данные в памяти, помогает процессору быстрее считывать данные. Исправление:

int i = y * Stride + x * cCount; 

Существует еще одна ошибка, которая скрыта в вашем коде, строки сканирования хранятся с ног на голову. Другими словами, сначала сохраняются данные для последней строки сканирования. Но только если BitmapData.Height не является отрицательным. Поскольку эта ошибка встречается как в методе GetPixel, так и в методах SetPixel, они отменяют друг друга. Правильный код будет (Высота - y - 1) * Stride + x * cCount.

Этот код не быстрее, чем Graphics.DrawImage(), метод, который вы всегда должны предпочесть.

+0

Пожалуйста, используйте предоставленную информацию для что вы не создали массив правильно. То же самое, вы снова используете Width вместо Stride. –

+0

Уважаемый Ганс, см. Ссылку. Я использовал '(Height - y - 1) * Stride + x * cCount'. http://i.imgur.com/MBfMvVh.png – anonymous

+1

Нет, проблема в вашем массиве '_imageData' ** **, он должен, конечно, содержать байты Stride * Height для хранения всего растрового изображения. Вы не делаете это достаточно большим. –

Смежные вопросы