2014-08-31 5 views
0

Ранее я писал об этой проблеме .. но проблема не была решена. Итак, я могу честно сказать, что это самое странное, необъяснимое осложнение, которое я когда-либо испытывал в своем опыте программирования.Более сложное исследование действительно странного неожиданного результата.

Проблема в том, когда я рисую bmp из буфера. enter image description here

Если я изменяю размер изображения, например, если я делаю ширину ширины> высота или высота>, изображения будут отображаться в обычном режиме. Посмотрите на код:

void bmp_bdraw (BYTE* BUFF) 
{ 

    word WIDTH, HEIGHT, W, H; // word - unsigned short 
    BYTE R, G, B; // BYTE - unsigned char 

    (!BUFF || !BUFF[COUNT-1]) ? // debug1 
     (error("Error in function 'bmp_bdraw'. There is no data to read from.")) : ;     

    WIDTH = BUFF[18] + BUFF[19] * 256; 
    HEIGHT = BUFF[22] + BUFF[23] * 256; 
    ofs = 54; 

    if(BUFF[0] != 'B' | BUFF[1] != 'M') error // debug2 
     ("Warning: Data identifier error in function 'bmp_bdraw' occurred. Invalid BMP file loaded."); 

    for(H=HEIGHT-1; H>=1; H--) 
    { 
     for(W=0; W<WIDTH; W++) 
     { 
      B = sgetc(BUFF); // fgetc-like function but from buff 
      G = sgetc(BUFF); 
      R = sgetc(BUFF); 

      setpen(R, G, B, 0, 1); // sets the color, transparancy and size of the pen 
      putpixel(W, H); // and puts the pixel at the right location 
     } 
    } 

    if(W != WIDTH || H > 1) // debug3 
     error("Error in function 'bmp_bdraw'. Rendering failed. The file might be damaged.");   

    if(real_fps < 11) 
     error("Too low fps rate."); // debug4 

Что я заметил в линии: for(H=HEIGHT-1; H>=1; H--) является H>=1 В прямом ничьи (ВМР для визуализации) функция (которая работает на 100%, и использует тот же метод), то H>=0 Однако .. если я меняю H>=1 на H>=0, он возвращает ошибку для переполнения буфера, возвратил функцией sgetc.

+1

Очень странное использование тройной ... –

+2

@Edenia: Почему? Вы использовали 'if' в трех других тестах отладки и нет веской причины использовать эту нелепую тройку в первом. Кстати, вы должны использовать логический ИЛИ '||' вместо этого побитового ИЛИ '' 'в теге debug2. Не пишите неряшливый код, сложнее рассуждать и отлаживать. – Blastfurnace

+0

OT: Использование 'H> 0' вместо' H> = 1' более понятно. – alk

ответ

2
  • Вместо putpixel предпочитают использовать любую функцию bitblt, если таковая имеется.
  • Пропустите paddding bytes (если есть) после окончания линии сканирования.

Обновленный код

numPadBytes = WIDTH * 3; 
numPadBytes %= 4; 
if(0 != numPadBytes) numPadBytes = 4 - numPadBytes; 

for(H=HEIGHT-1; H>=1; H--) 
{ 
for(W=0; W<WIDTH; W++) 
{ 
    B = sgetc(BUFF); // fgetc-like function but from buff 
    G = sgetc(BUFF); 
    R = sgetc(BUFF); 

    setpen(R, G, B, 0, 1); // sets the color, transparancy and size of the pen 
    putpixel(W, H); // and puts the pixel at the right location 
} 
for(tmp = 0; tmp < numPadBytes; ++tmp) 
{ 
    /* Ignore bytes */ 
    sgetc(BUFF); 
} 
} 

Вы должны объявить numPadBytes и tmp в int локальной к вашей функции.

+0

Извините, я не могу использовать какую-либо другую функцию, но 'putpixel' Эта функция хорошо работает везде. Например, в той же функции, но для прямого вывода из bmp. И о какой строке сканирования вы говорите? – Edenia

+0

Вы получаете правильный результат, если ширина bmp кратно 4? –

+0

Протестировано одно изображение с шириной, не кратное 4, и результат не удался. Но с тем, что кратно 4, результат в порядке. Это означает, что он имеет какое-то отношение к байтам заполнения, но ... Я не понимаю, почему .. почему прямая функция розыгрыша работает хорошо, а другая нет. Где разница. – Edenia

2

Вам необходимо пройти через шаг растрового изображения в направлении x. Каждая строка растрового изображения дополняется кратным четырем байтам.

Ваш код проходит по ширине (* 3 байта), но может быть 1..3 дополнительных байтов в конце строки. Эффект заключается в том, что вы слишком рано начинаете рисовать в выходной буфер, искажая все за первой строкой чуть больше слева.

Вы можете вычислить шаг следующим образом. Используйте это вместо ширины.

int stride = 4 * ((width * bytesPerPixel + 3)/4); // in bytes 

Таким образом, чтение данных изображения будет выглядеть примерно так ...

unsigned char *scan0 = buf + pixel_buffer_offset; 

for (int y = 0; y < height; ++y) 
{ 
    // sets the pointer to the beginning of the yth row 
    unsigned byte *row = scan0 + y * stride; 

    for (int x = 0; x < width; ++x) 
    { 
     unsigned char b = *row++; 
     unsigned char g = *row++; 
     unsigned char r = *row++; 

     setpen(r, g, b, 0, 1); 
     putpixel(x, y); 
    } 
} 

любой буфер вы пишете должно быть 0 инициализируется как мы не выписывая байты заполнения. Если вы не хотите этого делать, вам нужно будет пройти весь шаг каждой строки. Также убедитесь, что вы выделили для этого stride * height байтов, а не width * height * 3.

+0

Под 'bytesPerPixel' вы имеете в виду' bitsPerPixel'? Используйте шаг вместо WIDTH в петлях? Почему я устанавливаю указатель на начало строки? Я пытаюсь выяснить, ваш путь быстрее/короче/лучше, чем у Мохита. – Edenia

+0

Нет, я имею в виду байты на пиксель. Если вы хотите использовать биты на пиксель, добавьте 31 и разделите их на 32 (вместо 3 и 4). Да, вам нужно учитывать шаг в ваших циклах по той причине, о которой я говорил. Установка указателя на начало строки - это всего лишь один способ чтения буфера изображения. Указатель состоит в том, что ваш цикл неверен, поскольку он не учитывает байты заполнения в конце строки. –

+0

Желаю, чтобы я смог реализовать и протестировать свой путь, который делает вещь без циклов .. но она дает мне одну ошибку. Первый в строке: 'unsigned char * scan0 = BUFF [54];' говоря, что указатель разговор подозрительный. – Edenia

1

я предлагаю что-то, что не включает в себя только 1 строку и не вызывает головной боли:

ofs = ofs + WIDTH%4; 

во внешнем контуре, после внутреннего цикла. Я только что узнал, что работает. И я понятия не имею, почему люди приносят столько кода, если это делают. Надеюсь, что это поможет, если кто-то другой решит сделать из буфера.

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