Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Visual C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.08.2013, 22:15   #1
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию Сохранить массив битов как БМП изображение

Здравствуйте, познаю азы Visual studio, такой вопрос:
как сохранить массив битов в бмп файл? что бы в папке создалась картинка?
пробовал по разным статьям делать, вот что есть:
Код:
#include "stdafx.h"

#include <windows.h>
#include <tchar.h>


int _tmain(int argc, _TCHAR* argv[])
{

	int WX=320, WY=240;

	int bitmap[3*76800];  // truecolor bitmap data

	for (int i=0; i<3*WX*WY; i++)
			bitmap[i]=25;

	HDC hdc = CreateCompatibleDC(NULL);

	BITMAPINFO bm = { sizeof(BITMAPINFOHEADER), WX, WY, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
	HBITMAP bmp = CreateDIBSection( hdc, &bm, DIB_RGB_COLORS, (void**)&bitmap, 0,0 );
	
	bmp=CreateCompatibleBitmap(GetDC(0),WX, WY);
	

	return 0;
}
Как до ума довести - незнаю(
Использую VS express desktop 2012 если что
Помогите кто разбирается, уже голову сломал, кучу примеров перепробовал(((

Последний раз редактировалось hunter03; 05.08.2013 в 23:31.
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 09:58   #2
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

Нашел одно решение:
Код:
#include "stdafx.h"


#include <windows.h>
#include <tchar.h>


int _tmain(int argc, _TCHAR* argv[])
{

	int WX=320, WY=240;

	int red[3*320][3*320];  // truecolor bitmap data
	int green[3*320][3*320];  // truecolor bitmap data
	int blue[3*320][3*320];  // truecolor bitmap data

	for (int i=0; i<3*320; i++){
red[i][i]=1;
green[i][i]=1;
blue[i][i]=1;
	
	}
			

	//HDC hdc = CreateCompatibleDC(NULL);

	//BITMAPINFO bm = { sizeof(BITMAPINFOHEADER), WX, WY, 1, 88, BI_RGB, 0, 0, 0, 0, 0 };
	//HBITMAP bmp = CreateDIBSection( hdc, &bm, DIB_RGB_COLORS, (void**)&bitmap, 0,0 );
	
	//bmp=CreateCompatibleBitmap(GetDC(0),WX, WY);

	// use SetDIBits ?
	//SetPixel(hdc,1,10, RGB(BYTE(255),BYTE(255),BYTE(255)));
	//SetPixel(hdc,2,10, RGB(BYTE(255),BYTE(255),BYTE(255)));
//SetPixel(hdc,3,10, RGB(BYTE(255),BYTE(255),BYTE(255)));
//SetPixel(hdc, 4,10, RGB(BYTE(255),BYTE(255),BYTE(255)));

//	HBITMAP cross = (HBITMAP)LoadImage(NULL, 
	//	_T("C:\\Driver\\cross4.bmp") ,
	//	IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

FILE *f;
int w=320, h=240; int yres=10;
unsigned char *img = NULL;
int filesize = 54 + 3*w*h;  //w is your image width, h is image height, both int
if( img )
    free( img );
img = (unsigned char *)malloc(3*w*h);
memset(img,0,sizeof(img));

for(int i=0; i<w; i++)
{
    for(int j=0; j<h; j++)
{
    int x=i; int y=(yres-1)-j;
   int r = red[i][j]*255;
   int g = green[i][j]*255;
  int  b = blue[i][j]*255;
    if (r > 255) r=255;
    if (g > 255) g=255;
    if (b > 255) b=255;
    img[(x+y*w)*3+2] = (unsigned char)(r);
    img[(x+y*w)*3+1] = (unsigned char)(g);
    img[(x+y*w)*3+0] = (unsigned char)(b);
}
}

unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
unsigned char bmppad[3] = {0,0,0};

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

bmpinfoheader[ 4] = (unsigned char)(       w    );
bmpinfoheader[ 5] = (unsigned char)(       w>> 8);
bmpinfoheader[ 6] = (unsigned char)(       w>>16);
bmpinfoheader[ 7] = (unsigned char)(       w>>24);
bmpinfoheader[ 8] = (unsigned char)(       h    );
bmpinfoheader[ 9] = (unsigned char)(       h>> 8);
bmpinfoheader[10] = (unsigned char)(       h>>16);
bmpinfoheader[11] = (unsigned char)(       h>>24);

f = fopen("D:\image-draw4\cross4.bmp","w+");
fwrite(bmpfileheader,1,14,f);
fwrite(bmpinfoheader,1,40,f);
for(int i=0; i<h; i++)
{
    fwrite(img+(w*(h-i-1)*3),3,w,f);
    fwrite(bmppad,1,(4-(w*3)%4)%4,f);
}
fclose(f);
	/////////////////////////////////////////////////////////////////////////////////////////////////
В файле stdafx.h добавил еще строку :#define _CRT_SECURE_NO_WARNINGS перед всеми инклудами.
Приложение запускается, но появляется ошибка Stack Overflow
Не понимаю с чем связано, подскажите кто разбирается.
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 10:39   #3
Nuklon
Форумчанин
 
Аватар для Nuklon
 
Регистрация: 05.04.2012
Сообщений: 134
По умолчанию

Держи, по-простому накидал.

Код:
#include <windows.h>
#include <tchar.h>
#define  DIB_RGB(r, g, b) \
((DWORD)((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF)) 

void fill_rect(__int32*, int, int, int, int, int, DWORD);





// 24/32 бит
BOOL  SaveArrFile(const TCHAR* filename, const __int32* arr, 
                         int width, int height, int bpp = 24){

    if((bpp < 24) || (bpp > 32)) // только 24/32 бит
         return FALSE;

    DWORD p_row = (DWORD)((width * bpp + 31) & ~31) / 8uL;
    DWORD size  = (DWORD)(height * p_row);

    // формируем файловый заголовок
    BITMAPFILEHEADER  hdr;
    ZeroMemory(&hdr, sizeof(BITMAPFILEHEADER));
    hdr.bfType    = 0x4D42;
    hdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    hdr.bfSize    = hdr.bfOffBits + size;

    // заголовок описателя растра
    BITMAPINFO dib;
    ZeroMemory(&dib, sizeof(BITMAPINFO));
    dib.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
    dib.bmiHeader.biBitCount  = bpp;
    dib.bmiHeader.biCompression  = BI_RGB;
    dib.bmiHeader.biPlanes  = 1u;
    dib.bmiHeader.biWidth   = (long)width;
    dib.bmiHeader.biHeight  = (long)-height;
    dib.bmiHeader.biSizeImage   = size;
    dib.bmiHeader.biXPelsPerMeter = 11811L;
    dib.bmiHeader.biYPelsPerMeter = 11811L;
    dib.bmiHeader.biClrImportant  = 0uL;
    dib.bmiHeader.biClrUsed  = 0uL;

    // далее запись в файл
    HANDLE fp = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 
                                   CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(fp == INVALID_HANDLE_VALUE)
           return FALSE;

    // записываем заголовки...
    DWORD  dwr = 0uL;
    WriteFile(fp, (LPCVOID)&hdr, sizeof(BITMAPFILEHEADER), &dwr, NULL);
    WriteFile(fp, (LPCVOID)&dib.bmiHeader, sizeof(BITMAPINFOHEADER), &dwr, NULL);

    // запись массива пикселей
    if(bpp == 32) // 32-бит
           WriteFile(fp, (LPCVOID)arr, size, &dwr, NULL);
    else if(bpp == 24) { // 24-бит с дополнением до 32-разрядной границы

          BYTE   nil = 0u;
          int   cb  = sizeof(RGBQUAD);
          int  align = ((cb - ((width*bpp + 7) / 8) % cb) % cb);
		
          for(int y = 0; y < height; y++) {
               for(int x = 0; x < width; x++) 
                    WriteFile(fp, (LPCVOID)&arr[y*width+x], sizeof(RGBTRIPLE), &dwr, NULL);
			
                    for(int i = 0; i < align; i++) // до границы DWORD
                          WriteFile(fp, (LPCVOID)&nil, sizeof(BYTE), &dwr, NULL);
               }
   }

   FlushFileBuffers(fp);
   CloseHandle(fp);
   return TRUE;
}





int  main(void) {
    //массив пикселей
    __int32 arr[111*222] = {0};
    int cw = 222; 
    int ch = 111;

    // нарисуем что-нибудь
    DWORD rgb;
    int   sx  = ch / 5;
    int   sy  = cw / 10;
    for(int y = 0; y < 5; y++) {
         for(int x = 0; x < 10; x++) {
              rgb = DIB_RGB(rand()%2*0xFF, rand()%2*0xFF, rand()%2*0xFF);
              fill_rect(arr, cw, x*sx, y*sy, sx, sy, rgb);
        }
    }


    // сохраняем в файл
    if(SaveArrFile(_T("grid.bmp"), arr, cw, ch, 24))
           _putts(_T("Good save file."));
    else
           _putts(_T("Error save file !"));

    _gettchar();
    return 0;
}



// вывод прямоугольника
void fill_rect(__int32* arr, int width, int x, int y, int cx, int cy, DWORD color){
     for(int r = y; r <= (y + cy); r++) {
          for(int c = x; c <= (x + cx); c++)
               arr[r*width + c] = color;
     }
}
P.S. Используй лучше GDI+
Nuklon вне форума Ответить с цитированием
Старый 06.08.2013, 12:13   #4
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

Ого!!! спасибо!!!
не ожидал, спасибо!!!
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 12:54   #5
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

можно еще 1 вопрос?
какой функцией можно закрасить 1 пиксель?
я делаю так:
Код:
int  main(void) {
    //массив пикселей
    __int32 arr[320*240] = {0};
    int cw = 320; 
    int ch = 240;
	int red[320*240];
	int green[320*240];
	int blue[320*240];
	int Frame[320][240];
	//int Yaxe[320*240];
	 DWORD rgb;
	HDC hdc = CreateCompatibleDC(NULL);
	for(int col = 1; col < 320; col++){
		for(int row = 1; row < 240; row++){
			rgb = DIB_RGB(rand()%2*0xFF, rand()%2*0xFF, rand()%2*0xFF);
Frame[col][row]= rgb;

		}
	}

    // нарисуем что-нибудь
   

  int   sx  = 1;
   int   sy  = 1; int y=1; int x=1;
    for(int col = 1; col < 320; col++){
		for(int row = 1; row < 240; row++){
              
              //fill_rect(arr, cw, x+sx, y+sy, sx, sy, Frame[col][row]);
			  SetPixel(hdc,col,row, Frame[col][row]);
			  //SetPixel(hdc, 11,10, RGB(BYTE(133),BYTE(100),BYTE(025)));
        }
    }


    // сохраняем в файл
    if(SaveArrFile(_T("grid.bmp"), arr, cw, ch, 24))
           _putts(_T("Good save file."));
    else
           _putts(_T("Error save file !"));

    _gettchar();
    return 0;
}
но пиксели не закрашиваются, сохраняется черная картинка
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 13:08   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

Надо создать HBITMAP с помощью CreateDIBSection(), сделать SelectObject() и лишь потом делать SetPixel().

Если вы сами выделяете память под битмап, тогда либо сами меняете пиксели, либо создаете HBITMAP и используеете GDI, но тогда ваш буфер НЕ изменится.

Самое удобное - CreateDIBSection() - в этом случае можете менять пиксели сами, можете их записывать и можете менять картинку через GDI.

Edit:
В вашем примере, в рисуете в HDC, которое в памяти, т.е. изменений вы все равно не увидите.

Последний раз редактировалось waleri; 06.08.2013 в 13:10.
waleri вне форума Ответить с цитированием
Старый 06.08.2013, 13:19   #7
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

Если я правильно Вас понял - то нужно сделать так:
Код:
int bitmap[3*320*240];
	BITMAPINFO bm = { sizeof(BITMAPINFOHEADER), 320, 240, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
	HBITMAP bmp = CreateDIBSection( hdc, &bm, DIB_RGB_COLORS, (void**)&bitmap, 0,0 );
	HBITMAP *PTR=&bmp;
SelectObject(hdc, *PTR);
 int sx  = ch / 5;
    int   sy  = cw / 10;
   int y=1; int x=1;
    for(int col = 1; col < 320; col++){
		for(int row = 1; row < 240; row++){
              
            // fill_rect(arr, cw, x*sx, y*sy, sx, sy, rgb);
			 SetPixel(hdc,col,row, Frame[col][row]);
			 //  printf("%d",Frame[col][row]);
			  //SetPixel(hdc, 11,10, RGB(BYTE(133),BYTE(100),BYTE(025)));
        }
но вылетает переполнение стека
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 13:25   #8
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

не до конца понимаю, как пользоваться этими функциями. вся инфа на английском...
hunter03 вне форума Ответить с цитированием
Старый 06.08.2013, 13:48   #9
hunter03
Форумчанин
 
Регистрация: 05.05.2009
Сообщений: 244
По умолчанию

мм...а если не использовать те функции, а просто сделать прямоугольник по 1 пикселю? можно ли так?
hunter03 вне форума Ответить с цитированием
Старый 05.12.2013, 17:26   #10
FCSM_FAN
 
Регистрация: 21.05.2010
Сообщений: 7
По умолчанию

Здравствуйте. Недавно начал изучать c++ на Visual Studio 6.0. Тоже мучаюсь с получением картинки в с++
Попытался откомпилировать у себя программу которую накидал Nuklon, но компилятор выдал ошибку

C:\Program Files\Microsoft Visual Studio\MyProjects\probmp\prog.cpp(1 04) : error C2065: 'puts' : undeclared identifier
C:\Program Files\Microsoft Visual Studio\MyProjects\probmp\prog.cpp(1 08) : error C2065: 'getchar' : undeclared identifier

Где описываются эти операторы?

Пробовал добавить
Код:
#include<stdlib.h>
но безуспешно
FCSM_FAN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сохранить HTML в изображение? GroZa Общие вопросы Delphi 1 30.01.2011 15:46
Как сохранить изображение в файл имея HBITMAP WebbMan Общие вопросы C/C++ 1 17.01.2011 15:19
Как сохранить изображение с канвы в файл Marsel737 Общие вопросы Delphi 4 20.01.2010 19:44
Как сохранить изображение по ссылке? Indy. TwiX Работа с сетью в Delphi 4 29.11.2009 21:09
Как сохранить изображение Image и всё что на нём, в файл? Лукманов Александр Мультимедиа в Delphi 3 24.05.2009 00:16