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

Bitmapy, Implementacja w c++ Pytanie

Object Storage Arubacloud
0 głosów
741 wizyt
pytanie zadane 3 lutego 2019 w C i C++ przez Padoski Użytkownik (990 p.)

Siemka, chciałem wykonać następujące zadanie: Napisz program, który w pliku bmp podzieli obraz na 9 części (dzieląc wysokość na 3 równe części i szerokość podobnie)i część środkową pokoloruj na zadany kolor. Podobną procedurę powtórz dla pozostałych 8 elementów.

Wykładowca pokazał nam następujący kod:

#include<iostream>
#include<fstream>
#include<windows.h>

using namespace std;

void przetworzBMP(ifstream &s)
{
	BITMAPFILEHEADER bmpFile;
	BITMAPINFOHEADER bmpInfo;

	if (s.is_open())
	{
		//pobranie naglowka zajmuje 14 bajtow i 40 bajtow

		s.read((char*)&bmpFile, 14);
		s.read((char*)&bmpInfo, 40);

		//wydobycie informacji o rozmiarze pliku

		int szerokosc = bmpInfo.biWidth;
		int wysokosc = bmpInfo.biHeight;

		//dlugosc kazdego wiersza musi byc podzelna przez 4 - wiersz dopelniany jest zerami :-)
		int dopelnienie = 4-(3*szerokosc) % 4;
		cout << "szer=" << szerokosc<<endl;
		cout << "dop=" << dopelnienie << endl;

		int iloscDanych = bmpFile.bfSize - 14 - 40;


		//rezerwuje miejsce na zawartosc mapy bitow
		unsigned char* dane = new unsigned char[iloscDanych];

		//wczytanie danych

		s.read((char*)dane, iloscDanych);
		s.close();

		//utworzenie nowego pliku ze zmienionym kolorem
		ofstream nowy("klon.bmp");

		//kopiowani naglowków
		nowy.write((char*)&bmpFile, 14);
		nowy.write((char*)&bmpInfo, 40);

		//transformacja bitow

		unsigned char* wsk = dane;
		
		for (int i = 0; i < wysokosc; i++)
		{
			
			for (int j = 0; j < szerokosc; j++)
			{
				

					*wsk = (byte)255;
					*(wsk+1) = (byte)0;
					*(wsk+2) = (byte)100;
					wsk += 3;

			}
			wsk += dopelnienie;
			
		}
		
		nowy.write((char*)dane, iloscDanych);
		nowy.close();

		delete[] dane;


	}
}

int main()
{
	ifstream bmp("examp.bmp");
	przetworzBMP(bmp);

	system("PAUSE");
}

Maluje on całe zdjęcie na niebieski kolor.

Zauważyłem, że jesli zmienię na wysokosc/3 to poprostu pomaluję ten obrazek zaczynając od dołu na 1/3 wyskosci na kolor niebieski. Po zmianie będzie tak:

        
        

for (int i = 0; i < wysokosc/3; i++)
        {
            
            for (int j = 0; j < szerokosc; j++)
            {
                

                    *wsk = (byte)255;
                    *(wsk+1) = (byte)0;
                    *(wsk+2) = (byte)100;
                    wsk += 3;

            }
            wsk += dopelnienie;
            
        }

Teraz mam pytanie w jaki sposob mogę pomalować np 1/3 ale szerokosci obrazka ?  Poprostu chodzi mi o to aby rysowało na kolor niebieski 1/3 obrazka, lecz nie dzieląc wyskosci na 3 tylko szerokosc; Odrazu mówię , że zmienienie poprostu na szerokosc/3 w petli nie działa. Pojawiają się dziwne paski na calej szerokosci. Chcę poprostu dojść do tego by móc podzielić ten kod na 9 kawałków a potem sobie malować dowolny z nich. Tak jak w poleceniu powyżej. Jeśli ktoś mogłby mi to napisać jak to zrobic, bede mega wdzieczny. Pozdrawiam

1 odpowiedź

+1 głos
odpowiedź 3 lutego 2019 przez j23 Mędrzec (194,920 p.)
wybrane 4 lutego 2019 przez Padoski
 
Najlepsza
unsigned w3 = szerokosc / 3;
unsigned h3 = wysokosc / 3;
unsigned xByteOffset = w3 * 3;

unsigned char* scanline = dane + (h3 * scanlineSize);

for (unsigned i = 0; i < h3; ++i)
{
	unsigned char* p = scanline + xByteOffset;	

	for (unsigned j = 0; j < w3; ++j)
	{
		p[0] = (byte)0; 
		p[1] = (byte)0;
		p[2] = (byte)255;
		
		p += 3;
	}

	scanline += scanlineSize;
}

Coś w ten deseń. W poprzednim wątku podałem, jak obliczać scanlineSize.

komentarz 4 lutego 2019 przez Padoski Użytkownik (990 p.)

Mianowicie udalo mi się stworzyć 9 kwadratów, lecz w przypadku gdy obrazek ma 504x506(wysokosc,szerokosc) pixeli, to nie uzupelniam dolnej lini o wysokosci 1 pixela, oraz tej szerokosci nie uzepelnia o te dwa pixele, które powinne być dopełnione tym kolorem. Da sie jakoś na to zaradzić?. Zerknąłbyś w kod i poprawił lub wskazal co jest źle ? Pozdrawiam serdecznie :)

 

#include<iostream>
#include<fstream>
#include<windows.h>

using namespace std;

void przetworzBMP(ifstream &s)
{
	BITMAPFILEHEADER bmpFile;
	BITMAPINFOHEADER bmpInfo;

	if (s.is_open())
	{
		//pobranie naglowka zajmuje 14 bajtow i 40 bajtow

		s.read((char*)&bmpFile, 14);
		s.read((char*)&bmpInfo, 40);

		//wydobycie informacji o rozmiarze pliku

		int szerokosc = bmpInfo.biWidth;
		int wysokosc = bmpInfo.biHeight;


		//dlugosc kazdego wiersza musi byc podzelna przez 4 - wiersz dopelniany jest zerami 
		int dopelnienie = 4 - (3 * szerokosc) % 4;
		cout << "szer=" << szerokosc << endl;
		cout << "dop=" << dopelnienie << endl;



		//rezerwuje miejsce na zawartosc mapy bitow

		//wczytanie danych
		int scanlineSize;
		int iloscDanych;
		scanlineSize = ((bmpInfo.biWidth * bmpInfo.biBitCount + 31) / 32) * 4;
		iloscDanych = scanlineSize * bmpInfo.biHeight;

		unsigned char* dane = new unsigned char[iloscDanych];

		s.seekg(bmpFile.bfOffBits);
		s.read((char*)dane, iloscDanych);
		s.close();

		//utworzenie nowego pliku ze zmienionym kolorem
		ofstream nowy("klon.bmp");

		//kopiowani naglowków
		nowy.write((char*)&bmpFile, 14);
		nowy.write((char*)&bmpInfo, 40);

		//transformacja bitow

		unsigned char* wsk = dane;

		unsigned w3 = szerokosc / 3;
		unsigned h3 = wysokosc / 3;
		unsigned xByteOffset = w3 * 3;

		unsigned char* scanline = dane + (scanlineSize);

		for (unsigned i = 0; i < h3; ++i)
		{
			unsigned char* p = scanline;

			for (unsigned j = 0; j < w3*3; ++j)
			{
				if ((j >= 0) && (j <= w3)) { ///czerwony
					p[0] = (byte)255;
					p[1] = (byte)0;
					p[2] = (byte)0;

					p += 3;
				}
				if ((j > w3) && (j <= w3 * 2)) { ///zolty
					p[0] = (byte)255;
					p[1] = (byte)255;
					p[2] = (byte)0;

					p += 3;
				}

				if ((j > w3 * 2) && (j <= w3 * 3)) { ///rozowy
					p[0] = (byte)255;
					p[1] = (byte)0;
					p[2] = (byte)255;

					p += 3;
				}
			}


			scanline += scanlineSize;
		}

		for (unsigned i = 0; i < h3; ++i)
		{
			unsigned char* p = scanline;

			for (unsigned j = 0; j < w3*3 ; ++j)
			{
				if((j>0)&&(j<=w3)){ ///niebieski
				p[0] = (byte)0;
				p[1] = (byte)0;
				p[2] = (byte)255;

				p += 3;
				}
				 if ((j > w3) && (j <= w3*2)) {///czarny
					p[0] = (byte)0;
					p[1] = (byte)0;
					p[2] = (byte)0;

					p += 3;
				}

				if ((j > w3*2) && (j <= w3 * 3)) {///zielony
					p[0] = (byte)0;
					p[1] = (byte)255;
					p[2] = (byte)0;

					p += 3;
				}
			}

			scanline += scanlineSize;
		}
		for (unsigned i = 0; i < h3; ++i)
		{
			unsigned char* p = scanline;

			for (unsigned j = 0; j < w3*3 ; ++j)
			{
				if ((j > 0) && (j <= w3)) { ///błekitny
					p[0] = (byte)90;
					p[1] = (byte)255;
					p[2] = (byte)255;

					p += 3;
				}
				if ((j > w3) && (j <= w3 * 2)) { ///ciemnozielony
					p[0] = (byte)0;
					p[1] = (byte)70;
					p[2] = (byte)0;

					p += 3;
				}

				if ((j > w3 * 2) && (j <= w3 * 3)) {///fiolet
					p[0] = (byte)80;
					p[1] = (byte)0;
					p[2] = (byte)100;

					p += 3;
				}
			}

			scanline += scanlineSize;
		}








		nowy.write((char*)dane, iloscDanych);
		nowy.close();

		delete[] dane;


	}
}

int main()
{
	ifstream bmp("examp.bmp");
	przetworzBMP(bmp);

	system("PAUSE");
}

 

komentarz 4 lutego 2019 przez j23 Mędrzec (194,920 p.)
edycja 4 lutego 2019 przez j23

Było ten kod, który dałem, zapakować w jakąś funkcję, żeby nie powielać trzy razy tego samego.

 

Spróbuj tak

ofstream nowy("klon.bmp");

bmpInfo.biSize = sizeof(BITMAPINFOHEADER);
bmpFile.bfOffBits = sizeof(BITMAPFILEHEADER) + bmpInfo.biSize;
bmpFile.bfSize = bmpFile.bfOffBits + iloscDanych;

nowy.write((char*)&bmpFile, sizeof(BITMAPFILEHEADER));
nowy.write((char*)&bmpInfo, bmpInfo.biSize);
...

 

Popraw linię 61 na unsigned char* scanline = dane;

Podobne pytania

+1 głos
1 odpowiedź 670 wizyt
pytanie zadane 6 grudnia 2020 w C i C++ przez KumberTwo Dyskutant (8,270 p.)
0 głosów
0 odpowiedzi 115 wizyt
pytanie zadane 8 marca 2019 w Visual Basic przez Misterius Nowicjusz (120 p.)
0 głosów
1 odpowiedź 674 wizyt
pytanie zadane 3 stycznia 2017 w C i C++ przez ciastek2808 Początkujący (490 p.)

92,615 zapytań

141,465 odpowiedzi

319,774 komentarzy

61,996 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...