• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Tworzenie bitmapy w c++ bez dodatkowych bibliotek

+1 głos
329 wizyt
pytanie zadane 6 grudnia 2020 w C i C++ przez KumberTwo Dyskutant (8,270 p.)

Witam, próbuję napisać program generujący bitmapę, lecz jestem w tym temacie bardzo początkujący. Uczyłem się z tego kodu, lecz problem polega na tym, że tworzona przez ten kod bitmapa jest nie możliwa do otwarcia. Co powinienem zmienić, aby możliwe było normalne otwieranie tego pliku?

3
komentarz 6 grudnia 2020 przez j23 Mędrzec (176,760 p.)
edycja 6 grudnia 2020 przez j23

Może zacznij od opisu formatu -> link

Dodam, że ten kod, który podałeś jest kiepski, bo:

  • nie uwzględnia wyrównania struktur i ich pól (Data structure alignment)
  • nie uwzględnia tego, że wiersz bitmapy musi być wyrównany do 4
  • zmienne globalne (amatorszczyzna)
komentarz 6 grudnia 2020 przez mokrowski VIP (148,260 p.)
Ojtam ojtam... ale "avatar ma pod krawatem" :)
komentarz 7 grudnia 2020 przez KumberTwo Dyskutant (8,270 p.)

@j23, Dzięki za uwagi. Wybrałem ten kod, bo wydawało mi się, że jest czytelniejszy niż reszta. Czy byłbyś w stanie podlinkować jakiś taki porządny kod? Wątpię żebym był w stanie napisać coś lepszego, bo jak powiedziałem robię coś podobnego pierwszy raz.

1
komentarz 7 grudnia 2020 przez j23 Mędrzec (176,760 p.)
Można poprawić kod, który podałeś, tylko musisz powiedzieć, w jakim formacie chcesz zapisywać tę bitmapę (chodzi o bity).
komentarz 7 grudnia 2020 przez KumberTwo Dyskutant (8,270 p.)
Myślę że format bmp jest ok, ale dałoby się zapisać go w np. jpg? Jeśli tak, to myślę, że byłaby to lepsza opcja.
komentarz 7 grudnia 2020 przez j23 Mędrzec (176,760 p.)
Nie o to pytałem. Do JPEG-a trzeba zewnętrznej biblioteki (chyba że system, na którym to piszesz, oferuje jakieś API).
komentarz 7 grudnia 2020 przez KumberTwo Dyskutant (8,270 p.)

A, faktycznie. Myślę, że system zapisywania bitów jest mi zupełnie obojętny. Najważniejsze dla mnie jest to, żebym mógł ten plik otworzyć laugh

1 odpowiedź

+1 głos
odpowiedź 7 grudnia 2020 przez j23 Mędrzec (176,760 p.)
wybrane 8 grudnia 2020 przez KumberTwo
 
Najlepsza

Tu masz poprawiony kod:

#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector> 

#pragma pack(push)
#pragma pack(1)

struct BmpHeader {
	char bitmapSignatureBytes[2];
	uint32_t sizeOfBitmapFile;
	uint32_t reservedBytes;
	uint32_t pixelDataOffset;
};

struct BmpInfoHeader {
	uint32_t sizeOfThisHeader;
	int32_t width;
	int32_t height;
	uint16_t numberOfColorPlanes;
	uint16_t colorDepth;
	uint32_t compressionMethod;
	uint32_t rawBitmapDataSize;
	int32_t horizontalResolution;
	int32_t verticalResolution;
	uint32_t colorTableEntries;
	uint32_t importantColors;
};

struct Pixel {
	uint8_t blue;
	uint8_t green;
	uint8_t red;
};

#pragma pack(pop)



void save24bitsBitmap(std::ostream &os, size_t w, size_t h, const Pixel* data)
{
	BmpHeader bmpHdr;
	BmpInfoHeader bmpInfo;

	bmpInfo.sizeOfThisHeader = sizeof(BmpInfoHeader);
	bmpInfo.width = w; 
	bmpInfo.height = h; 
	bmpInfo.numberOfColorPlanes = 1; 
	bmpInfo.colorDepth = 24;
	bmpInfo.compressionMethod = 0;
	bmpInfo.rawBitmapDataSize = 0; 
	bmpInfo.horizontalResolution = 3780; 
	bmpInfo.verticalResolution = 3780; 
	bmpInfo.colorTableEntries = 0;
	bmpInfo.importantColors = 0;

	size_t scanLineSize = 4 * ((24 * w + 31) / 32);

	std::memcpy(bmpHdr.bitmapSignatureBytes, "BM", 2);
	bmpHdr.pixelDataOffset = sizeof(bmpHdr) + sizeof(bmpInfo);
	bmpHdr.sizeOfBitmapFile = bmpHdr.pixelDataOffset + scanLineSize * h;
	bmpHdr.reservedBytes = 0;

	os.write(reinterpret_cast<char*>(&bmpHdr), sizeof(BmpHeader));
	os.write(reinterpret_cast<char*>(&bmpInfo), sizeof(BmpInfoHeader));

	size_t widthInBytes = sizeof(Pixel) * w;
	size_t paddingSize = scanLineSize - widthInBytes;
	char pad[3] = { 0 };

	while (h--) {
		os.write(reinterpret_cast<const char*>(data), widthInBytes);
		os.write(pad, paddingSize);
		data += w;
	}
}


int main(int argc, char** argv)
{
	std::ofstream os("output.bmp", std::ios::binary);
	Pixel v[100][100] = { 0, 0, 0 };

	for(int i = 0; i < 100; ++i) {
		v[i][50] = v[50][i] = { 255, 255, 255 };
	}

	save24bitsBitmap(os, 100, 100, v[0]);
	return 0;
}

Nie wiem, czy dyrektywy #pragma będą działać na twoim kompilatorze, ale na g++ i VC działają, więc problemów być nie powinno.

komentarz 8 grudnia 2020 przez KumberTwo Dyskutant (8,270 p.)
#pragma i cała reszta działa. Dziękuję bardzo.

Podobne pytania

0 głosów
1 odpowiedź 392 wizyt
pytanie zadane 3 stycznia 2017 w C i C++ przez ciastek2808 Początkujący (490 p.)
0 głosów
1 odpowiedź 288 wizyt
pytanie zadane 3 lutego 2019 w C i C++ przez Padoski Użytkownik (990 p.)
0 głosów
0 odpowiedzi 75 wizyt
pytanie zadane 8 marca 2019 w Visual Basic przez Misterius Nowicjusz (120 p.)

88,677 zapytań

137,289 odpowiedzi

306,653 komentarzy

58,873 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...