Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сохранение 4-битних bmp, Есть вопросьі 
V
    Опции темы
Slay1
Дата 4.6.2006, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 17.5.2006

Репутация: нет
Всего: нет



Сначала первьій ворос - не знаю как заполнить некоторьіе поля заголовка.
Значит огласил я 2 структурьі:
Код

typedef struct
{
    unsigned char type[2];  /* This specifies the type of file. This should be
                                    equal to BM */
    unsigned long file_size;  /* This gives the bitmap size in bytes */
    unsigned int reserved_1;  /* This is reserved and must be 0 */
    unsigned int reserved_2;  /* This is also reserved and must also be 0 */
    unsigned long offset;  /* This specifies the number of bytes from the
                                starting of the bitmap to where the actual
                                data part starts */
}BITMAP_FILE_HEADER;


/* The Bitmap Information Header */

typedef struct
{
    unsigned long structure_size;  /* This specifies in bytes the size of the
                                    header. This must be equal to 40. */
    long width;  /* This specifies the width of bitmap in pixels */
    long height;  /* This specifies the height of bitmap in pixels */
    unsigned int number_of_color_planes;  /* This specifies the number of
                                            color planes */
    unsigned int bits_per_pixel;  /* This specifies the bits per pixel i.e.
                                    the total number of colors in the bitmap */
    unsigned long compression;  /* This specifies the type of RLE compression in
                                the bitmap. No compression means that the
                                value will be 0. */
    unsigned long image_size;  /* This specifies the size of image in pixels
                                i.e. width x height */
    long horizontal_pixels_per_meter;  /* This specifies the horizontal
                                            resolution of image as pixels per
                                            meter */
    long vertical_pixels_per_meter;  /* This specifies the vertical resolution
                                        of image as pixels per meter */
    unsigned long colors_used;  /* This specifies the colors used in the
                                    bitmap. For 4-bit image this value is 0 */
    unsigned long important_colors;  /* This specifies the minimum number of
                                        important colors in the bitmap */
}BITMAP_INFORMATION_HEADER;


Но не знаю какие значения дать некоторьім полям(те, что закомментированьі):

Код

bitmap_header.type[0]='B';
bitmap_header.type[1]='M';
//bitmap_header.file_size;
bitmap_header.reserved_1=0;
bitmap_header.reserved_2=0;
//bitmap_header.offset;

bitmap_information.structure_size=40;
bitmap_information.width=getmaxx()+1;
bitmap_information.height=getmaxy()+1;
//bitmap_information.number_of_color_planes;
bitmap_information.bits_per_pixel=4;
bitmap_information.compression=0;
//bitmap_information.image_size;
//bitmap_information.horizontal_pixels_per_meter;
//bitmap_information.vertical_pixels_per_meter;
//bitmap_information.colors_used;
//bitmap_information.important_colors;


//bitmap_header.file_size; - насколько я понимаю размер файла должен бьіть (getmaxx()*getmaxy())/2+54 ? Но на практике, размер файла, сделаного, например, в paint немножко больше..
//bitmap_header.offset; - смещение, я думал оно равно 54, но для примера открьіл файл и оно там 118. Не понимаю, так как оно вьічисляєтся?
//bitmap_information.number_of_color_planes; - єтого вообще не понимаю
//bitmap_information.image_size; - не понял в каком формате писать
//bitmap_information.horizontal_pixels_per_meter; - как єто и следующие вьічислить тоже не понимаю
//bitmap_information.vertical_pixels_per_meter; ^
//bitmap_information.colors_used;  - тут и в следующем насколько я поняо должно бьіть 16, так?
//bitmap_information.important_colors;

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


Код

 if((bitmap_file=fopen(file_name,"wb"))==NULL) /* Opening bitmap file in read-only mode */
   return(FILE_READING_ERROR);


 if(fwrite(&bitmap_header,sizeof(BITMAP_FILE_HEADER),1,bitmap_file)!=1)
   return(FILE_HEADER_READING_ERROR);


 if(fwrite(&bitmap_information,sizeof(BITMAP_INFORMATION_HEADER),1,bitmap_file)!=1)
   return(INFO_HEADER_READING_ERROR);

 fseek(bitmap_file,54,SEEK_SET);
 for(screen_y=getmaxy();screen_y>y-1;screen_y--)
   {
    for(screen_x=x;x<getmaxx();screen_x+=2)
      {
       pixel=(getpixel(screen_x,screen_y)<<4)&(getpixel(screen_x+1,screen_y));
       fputc(pixel,bitmap_file);
      }
   }
 fclose(bitmap_file);
}


Но получил просто бмп, весь залитьій черньім цветом...
Программа остановливалась только ctrl+break на єтой строке - fputc(pixel,bitmap_file);
Помогите пожалуйста.  

Это сообщение отредактировал(а) Slay1 - 4.6.2006, 15:17
PM MAIL   Вверх
ptr
Дата 5.6.2006, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 1
Всего: 14



bitmap_header.offset - смещение относительно начала файла до таблицы цветов, длина которой может изменяться от 8 до 1024 байт. Правда не все bmp имеют такую таблицу (например в 24 битных её нет).

bitmap_header.file_size - размер всего файла (заголовки, таблица цветов и сам массив).

bitmap_information.number_of_color_planes = 1.

bitmap_information.image_size - размер картинки в байтах. Оно равно width*height*bits_per_pixel/8. По-моему если bmp не сжата (compression=0), то здесь надо ставить 0, хотя я в этом не уверен.

bitmap_information.colors_used - количество используемых цветов из таблицы. Этот параметр имеет значение только для сжатых картинок. Если color_used равен 0, то используется максимально возможное количество цветов (в твоём случае 16).

bitmap_information.important_colors - количество важных цветов - число цветов, которые необходимы для того, чтобы изобразить рисунок. Если значение равно 0, то все цвета считаются важными.

bitmap_information.horizontal_pixels_per_meter, bitmap_information.vertical_pixels_per_meter - горизонтальное и вертикальное разрешение устройства. Можешь задавать здесь свои значения.

 


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Slay1
Дата 5.6.2006, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 17.5.2006

Репутация: нет
Всего: нет



Цитата(ptr @  5.6.2006,  08:36 Найти цитируемый пост)
bitmap_header.file_size - размер всего файла (заголовки, таблица цветов и сам массив).

Как узнать размер файла? По логике ширина*висота+54, на на практике виходит где-то на 100-200 байт больше, тогда какая же окончательная формула расчета размера файла так и не могу понять... 


Цитата(ptr @  5.6.2006,  08:36 Найти цитируемый пост)
bitmap_header.offset - смещение относительно начала файла до таблицы цветов, длина которой может изменяться от 8 до 1024 байт. Правда не все bmp имеют такую таблицу (например в 24 битных её нет).

В 4 битных тоже нет, то есть смещение до таблици цветов 0??
Но я для примеру читал один 16-цветной бмп, там оффсет равен 118 smile ... Ничего не понимаю...
 
PM MAIL   Вверх
Earnest
Дата 5.6.2006, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вот код для записи заголовка для некомпрессированного bmp. Выдрано из программы с мясом, но, надеюсь, разобраться поможет. Объект Dib, который встречается в коде - это оболочка вокруг DIBSection.

Код

   // Заполнение заголовка файла в зависимости от размера изображения
   BITMAPFILEHEADER Bmfh ;
   Bmfh.bfType = 0x4d42 ; // идентификатор "ВМ" == 0x4d42
   Bmfh.bfReserved1 = 0 ;
   Bmfh.bfReserved2 = 0 ;

   BITMAPINFOHEADER Bmih ;

   m_nFileBpLine = BytesPerBMPLine (pDib->Width(), pDib->BitCount()) ;

   // заполняем LPBITMAPINFO.BITMAPINFOHEADER
   Bmih.biSize = sizeof(BITMAPINFOHEADER) ;
   Bmih.biWidth = pDib->Width() ;
   Bmih.biHeight = pDib->Height() * (Format().BottomUp() ? 1 : -1) ;
   Bmih.biSizeImage = m_nFileBpLine * Bmih.biHeight ;
   Bmih.biBitCount = pDib->BitCount() ;
   Bmih.biPlanes = 1 ;

   if (Bmih.biBitCount < 16)
      Bmih.biClrUsed = min (1u << Bmih.biBitCount, pDib->ClrUsed()) ;
   else
      Bmih.biClrUsed = 0 ;

   Bmih.biClrImportant = 0 ;
   Bmih.biCompression = BI_RGB ;
   Bmih.biXPelsPerMeter = Bmih.biYPelsPerMeter = pDib->Dpm() ;

   Bmfh.bfOffBits = sizeof Bmfh + sizeof Bmih + Bmih.biClrUsed * sizeof (RGBQUAD) ;
   Bmfh.bfSize = Bmfh.bfOffBits + Bmih.biSizeImage ;

   out.write ((const char*)&Bmfh, sizeof Bmfh) ;
   out.write ((const char*)&Bmih, sizeof Bmih) ;

   if (Bmih.biClrUsed)
   {
      CPaletteIP pPalette = pDib->QueryPalette () ;
      ASSERT( pPalette ) ;

      for (int i=0; i < (int)pPalette->ClrUsed(); ++i)
      {
         RGBQUAD rgb = pPalette->GetColor (i) ;
         out.write ((const char*)&rgb, sizeof rgb) ;
      }
   }


Вычисление длины строки:
Код

   UINT BytesPerBMPLine (UINT nWidth, UINT nBitCnt)
   {
      return (((nWidth * nBitCnt + 7) >> 3) + 3) & ~3 ;
   }
 


--------------------
...
PM   Вверх
ptr
Дата 5.6.2006, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 1
Всего: 14



Как это таблицы цветов нет в 4 битных bmp? Как же тогда кодируется массив, содержащий картинку? Таблицы цветов нет только в 24 битных (поскольку там используется RGB) и, по-моему, ещё в 16 битных.

Размер таблицы цветов равен 4*2^n для n-битного bmp (2^n - количество цветов). В твоём случае offset равен 54+4*2^4=118, что и было в файле.

Примерный размер bmp файла равен 54+4*2^n+(width*height*n)/8, где width и height - размер картинки в пикселях (примерный поскольку размер таблицы цветов может быть разный). 


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Slay1
Дата 5.6.2006, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 17.5.2006

Репутация: нет
Всего: нет



Ну никак не виходит разобраться. Вроде как все елементьі хедера заполнил нормально, но сохраняет просто черний екран, и потом файл в пейнте даже не хочет редактироваться...

Код

unsigned char savebitmap(unsigned char *file_name )
{
 FILE *bitmap_file;

 BITMAP_FILE_HEADER bitmap_header;
 BITMAP_INFORMATION_HEADER bitmap_information;

 int screen_x, screen_y;
 char pixel;

bitmap_header.type[0]='B';
bitmap_header.type[1]='M';
bitmap_header.file_size=118+(getmaxx()+1)*(getmaxy()+1)/2;
bitmap_header.reserved_1=0;
bitmap_header.reserved_2=0;
bitmap_header.offset=118;

bitmap_information.structure_size=40;
bitmap_information.width=getmaxx()+1;
bitmap_information.height=getmaxy()+1;
bitmap_information.number_of_color_planes=1;
bitmap_information.bits_per_pixel=4;
bitmap_information.compression=0;
bitmap_information.image_size=bitmap_information.width*bitmap_information.height*bitmap_information.bits_per_pixel/8;
bitmap_information.horizontal_pixels_per_meter=96;
bitmap_information.vertical_pixels_per_meter=96;
bitmap_information.colors_used=0;
bitmap_information.important_colors=0;

 if((bitmap_file=fopen(file_name,"wb"))==NULL)
   return(FILE_READING_ERROR);

 if(fwrite(&bitmap_header,sizeof(BITMAP_FILE_HEADER),1,bitmap_file)!=1)
   return(FILE_HEADER_READING_ERROR);

 if(fwrite(&bitmap_information,sizeof(BITMAP_INFORMATION_HEADER),1,bitmap_file)!=1)
   return(INFO_HEADER_READING_ERROR);

 for(screen_y=getmaxy();screen_y>=0;screen_y--)
   {
    for(screen_x=0;screen_x<=getmaxx();screen_x+=2)
      {
       pixel=(getpixel(screen_x,screen_y)<<4)|(getpixel(screen_x+1,screen_y));
       fwrite(&pixel,sizeof(pixel),1,bitmap_file);
      }
   }
 fclose(bitmap_file);
}
  

Это сообщение отредактировал(а) Slay1 - 5.6.2006, 20:16
PM MAIL   Вверх
ptr
Дата 6.6.2006, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 1
Всего: 14



А где таблица цветов? Если бы у тебя был 24 битный bmp, то такое решение вполне бы подошло. Но у тебя 4 битный bmp и тебе надо описать каждый используемый цвет. Потом в массиве каждый пиксель будет описываться одним байтом - ссылкой на место, где содержится описание этого цвета.

Вот кстати неплохой пример.  

Это сообщение отредактировал(а) ptr - 6.6.2006, 11:11


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
ptr
Дата 6.6.2006, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 1
Всего: 14



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


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Slay1
Дата 6.6.2006, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 17.5.2006

Репутация: нет
Всего: нет



Цитата(ptr @  6.6.2006,  11:05 Найти цитируемый пост)
Вот кстати неплохой пример.  

Большое, огромное, жирное спасибо!
Все, разобрался.

 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0824 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.