• 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

VPS Starter Arubacloud
+1 głos
620 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 (194,920 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 Mędrzec (155,460 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 (194,920 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 (194,920 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 (194,920 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ź 642 wizyt
pytanie zadane 3 stycznia 2017 w C i C++ przez ciastek2808 Początkujący (490 p.)
0 głosów
1 odpowiedź 667 wizyt
pytanie zadane 3 lutego 2019 w C i C++ przez Padoski Użytkownik (990 p.)
0 głosów
0 odpowiedzi 111 wizyt
pytanie zadane 8 marca 2019 w Visual Basic przez Misterius Nowicjusz (120 p.)

92,454 zapytań

141,262 odpowiedzi

319,099 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...