2015-03-19 3 views
0

Я пытаюсь написать простую функцию, которая сбрасывает некоторые данные изображения в виде растрового изображения. Я генерирую данные 3601 x 3601. Я проверил в отладчике, что все данные, переданные функции, верны. Я также подтвердил, что размер пэда такой, какой я ожидал бы для 24-битного BMP шириной 3601 (padSize = 1).Почему мой писатель bmp не работает?

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

void SaveBMPData(string fname, unsigned char *data, int imgWid, int imgHei) 
{ 

    ofstream file; 
    file.open(fname.c_str(), std::ios::out); 

    if (file.is_open()) 
    { 
     //string fname = "APnormal.bmp"; 
     cout << "INFO >> Saving BMP data: " << fname << "." << endl; 

     //write header 
     unsigned char fileinfo[14] = { 
      'B', 'M', // magic 
      0, 0, 0, 0, // size in bytes 
      0, 0, // app data 
      0, 0, // app data 
      40 + 14, 0, 0, 0 // start of data offset 
     }; 
     unsigned char info[40] = { 
      40, 0, 0, 0, // info hd size 
      0, 0, 0, 0, // width 
      0, 0, 0, 0, // heigth 
      1, 0, // number color planes 
      24, 0, // bits per pixel 
      0, 0, 0, 0, // compression is none 
      0, 0, 0, 0, // image bits size 
      0x13, 0x0B, 0, 0, // horz resoluition in pixel/m 
      0x13, 0x0B, 0, 0, // vert resolutions (0x03C3 = 96 dpi, 0x0B13 = 72 dpi) 
      0, 0, 0, 0, // #colors in pallete 
      0, 0, 0, 0, // #important colors 
     };  

     int w = imgWid; 
     int h = imgHei; 

     int padSize = (4 - ((w * 3) % 4)) % 4; 
     int sizeData = w*h * 3 +h*padSize; 
     int sizeAll = sizeData + sizeof(fileinfo) + sizeof(info); 

     fileinfo[2] = (unsigned char)(sizeAll); 
     fileinfo[3] = (unsigned char)(sizeAll >> 8); 
     fileinfo[4] = (unsigned char)(sizeAll >> 16); 
     fileinfo[5] = (unsigned char)(sizeAll >> 24); 

     info[4] = (unsigned char)(w); 
     info[5] = (unsigned char)(w >> 8); 
     info[6] = (unsigned char)(w >> 16); 
     info[7] = (unsigned char)(w >> 24); 

     info[8] = (unsigned char) (h); 
     info[9] = (unsigned char) (h >> 8); 
     info[10] = (unsigned char)(h >> 16); 
     info[11] = (unsigned char)(h >> 24); 

     info[20] = (unsigned char)(sizeData); 
     info[21] = (unsigned char)(sizeData >> 8); 
     info[22] = (unsigned char)(sizeData >> 16); 
     info[23] = (unsigned char)(sizeData >> 24); 

     file.write((char*)fileinfo, sizeof(fileinfo)); 
     file.write((char*)info, sizeof(info)); 

     unsigned char *charbuffer = new unsigned char[w * 3 + padSize]; 

     for (int y = 0; y<h; y++) 
     { 
      for (int x = 0; x<w; x++) 
      { 
       unsigned char red = data[(x + y*imgWid) * 3]; 
       unsigned char green = data[(x + y*imgWid) * 3 + 1]; 
       unsigned char blue = data[(x + y*imgWid) * 3 + 2]; 
       charbuffer[x * 3 ] = blue; 
       charbuffer[x * 3 + 1] = green; 
       charbuffer[x * 3 + 2] = red; 

      } 
      file.write((char *)(void*)charbuffer, w*3+padSize); 

     } 
     file.close(); 
     delete [] charbuffer; 
    } 
    else 
    { 
     cout << "can't read file.\n"; 
    } 

} 

ответ

0

Вы сохранили растровое изображение от краски в виде 24 бит BMP?

Я бы очень хотел получить код в Интернете, например здесь: http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.html и посмотреть на этот код.

Я бы не использовал массивы со значениями и комментариями (info, fileinfo) и использовал реальные конкретные структуры для определения свойств.

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

+0

К сожалению, для меня я не могу использовать внешнюю библиотеку. Мой заголовок, я считаю, прав, как будто я изменяю данные вокруг, чтобы установить rgb в те же долины в поступающих данных, которые он пишет правильно. Только когда img-данные представляют собой массив случайных величин, он запутывается и выводит слишком много информации. Спасибо за ссылку. Я посмотрю. – user3758015

+0

Какие размеры вашего файла? Я ожидал бы, что 3601x3601x3 = 38901603 + padding (3601 * 1) + информация заголовка будет примерно примерно такого размера. – Mike

+0

Правильный размер файла должен быть 38,905,258. Мой файл составляет 38 926 864. который составляет 6 дополнительных байтов в строке. – user3758015

1

Вам необходимо открыть файл в двоичном режиме, иначе любой компонент пикселя со значением 0x0a приведет к записи в файл 0x0d 0x0a.

file.open(fname.c_str(), std::ios::out | std::ios::binary); 
+0

Хорошая точка, если она открывается по умолчанию в текстовом режиме :) Один из способов определить - использовать ** long pos = file.tellp(); ** после каждой записи указать, где находится файл, и если он написал больше, чем вы ожидали. – Mike

+0

Это было правильное исправление, спасибо большое! Это исправило мою проблему !!! вы джентльмены и святые! – user3758015