2014-10-09 2 views
0
// load pixels into an image 
     this.image = new BufferedImage(this.width, 
             this.height, 
             BufferedImage.TYPE_INT_RGB); 

     // get actual image data for easier pixel loading 
     byte[] iData = new byte[this.size - 54]; 
     for(int i = 0; i < this.size - 54; i++) { 
      iData[i] = this.data[i+54]; 
     } 

     // start from bottom row 
     for(int y = this.height-1; y >= 0; y--) { 
      for(int x = 0; x < this.width; x++) { 
       int index = (this.width*y + x) * 3; 
       int b = iData[index]; 
       int g = iData[index+1]; 
       int r = iData[index+2]; 

       //System.out.format("R: %s\nG: %s\nB: %s\n\n", r, g, b); 

       // merge rgb values to single int 
       int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff); 

       // build image from bottom up 
       this.image.setRGB(x, this.height-1-y, rgb); 
      } 
     } 

Я читаю значения RGB из растрового изображения. Мой массив байтов iData верен, поскольку я проверил его против шестнадцатеричного редактора. Однако, когда я запускаю этот цикл, мое выходное изображение искажено (см. Рисунок). Я часами пытаюсь понять, почему это происходит?Растровое изображение выходит из деформированного

Входное изображение является канадским флагом.

вывода изображения:

warped canada flag

+2

Имеет ли ваш входной файл 4 строки, выровненные по строкам? Некоторые форматы добавляют дополнение к концу каждой строки, чтобы каждая строка была кратной 4 байтам. – immibis

+0

Да, это так! Зачем? – Tetramputechture

+1

Потому что вы, вероятно, не учитываете это. – immibis

ответ

0

Я не учета нулевого байта заполнения по ширине, для которых формула является

WidthWithPadding = потолок ((ш * ColorDepth)/32) * 32.

0

Обычно изображения имеют ширину, глубину (бит на пиксель) и шаг. Обычно шаг - это не только ширина * глубины, но и заполненная некоторой суммой (часто используется для выравнивания каждой строки до 16-разрядной границы для причин доступа к памяти).

Ваш код, как представляется, не учитывает шаг или любое дополнение, которое объясняет смещение при прохождении изображения. Я удивлен, что цвета не переключаются (предполагая, что прокладка имеет тот же размер, что и пиксель), но эти неопределенные значения вызывают черную полосу через изображение.

Вместо того чтобы умножать (this.width*y + x) * 3 для получения вашего индекса, вы должны использовать (this.stride*y + x) * 3 с соответствующим значением для шага. Кажется, что BufferedImage class не может обеспечить это каким-либо очевидным образом, поэтому вам нужно рассчитать или извлечь это в противном случае.

0

Общая проблема заключается в том, что ваш код сконфигурировал шаг (расстояние между строками в байтах) с шириной (количество байтов в строке); в выровненных форматах данных это не обязательно одно и то же. Общий результат этого - получить вид перекоса, который вы видите, поскольку вторая строка начинается с последнего байта (ов) первой строки, третья строка начинается со второго-последнего байта (ов) второго ряда и т. д.

Первое, что вам нужно сделать, это рассчитать шаг данных и использовать это как коэффициент умножения для строки. Вот упрощенный цикл, который также является несколькими более эффективным, чем умножения на каждый пиксель основе:

int stride = (this.width + 3) & ~3; // rounds up to the nearest multiple of 4 
for (int y = 0; y < this.height; y++) { 
    int idx = y*stride; 
    for (int x = 0; x < this.width; x++) { 
     int b = iData[idx++]; 
     int g = iData[idx++]; 
     int a = iData[idx++]; 
     // etc. 
    } 
} 

Обратите внимание, что скругление трик выше ((w + a - 1) & ~(a - 1)) работает только для значений мощности из-двух; более общий вид скругления трюка:

int stride = (width + stride - 1)/stride*stride; 

хотя это очень редко можно найти выравнивания, которые не являются степенью 2, в первую очередь.

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