[英]C++ - 10 most popular colors of a bitmap
我正在研究C ++项目-应该找到位图的高度,宽度和10种最流行的颜色。 找到高度和宽度不是问题,我在几分钟内就完成了,但是在找到这些颜色时遇到了严重的问题。
这是我的代码:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
void main(int argc, char *argv[])
{
ifstream plik;
plik.open(argv[1]);
if (plik.good())
{
cout << "Bitmapa zaladowana poprawnie." << endl;
// Idziemy do 10 bajtu w pliku - tam jest zapisany numer bajtu pod ktorym zaczynaja sie informacje o pixelach
plik.seekg(10, ios::beg);
int adresPixeli = 0;
plik.read((char*)&adresPixeli, sizeof(int));
// Idziemy na 18 bajt w pliku (pod nim jest zapisana szerokosc, a od 22 jest wysokosc)
plik.seekg(18, ios::beg);
int szerokosc, wysokosc;
// Zapisujemy szerokosc do zmiennej szerokosc (w pixelach)
plik.read((char*)&szerokosc, sizeof(int));
plik.read((char*)&wysokosc, sizeof(int));
cout << "Szerokosc obrazu to: " << szerokosc << endl;
cout << "Wysokosc obrazu to: " << wysokosc << endl;
// Przejscie na 28 bajt w pliku, pod nim jest zapisana informacja o tym ile bitow ma kazdy pixel
plik.seekg(28, ios::beg);
int iloscBitow = 0;
// Read number of bytes used per pixel
plik.read((char*)&iloscBitow, sizeof(short int));
// Jesli mamy wysokosc i szerokosc to mozemy stworzyc tablice ktora bedzie przechowywac wartosci kolorow pixeli
// Rozmiar tablicy musi byc rowny szerokosc * wysokosc, a jeden pixel ma 3 bajty informacji
// RGB - red green blue, czyli informacje o kolorach (po 1 bajcie na red, green i blue)
// Alokacja pamieci dla tablicy ktora bedzie przechowywac wartosci bitow.
int *mapaPixeli = new int [szerokosc * wysokosc];
// Przejście do bajtu pod ktorym zaczynaja sie pixele
plik.seekg(adresPixeli, ios::beg);
// Zmienna do ktorej bedziemy wczytywac wartosc pixela (kolor - RGB, zapisany szesnastkowo np. 0xFFFFFF to kolor bialy, a
// 0x000000 to kolor czarny
// pozniej policzymy najczesciej wystepujace kolory i je wypiszemy
int wartoscPixela;
for (int i = 0; i < szerokosc * wysokosc; i++)
{
wartoscPixela = 0;
// Wczytujemy 3 bajty - bo na tylu zapisane sa informacje odnosnie 1 pixela, do zmiennej wartoscPixela
plik.read((char*)&wartoscPixela, 3);
// Zapisujemy wartosc w tablicy pixeli
if (iloscBitow == 24)
mapaPixeli[i] = wartoscPixela;
}
for (int i = 0; i < 100; i++)
cout << hex << mapaPixeli[i] << " ";
// Szukanie 10 najpopularniejszych kolorow
int max_count = 0;
int wynik;
// Przechowuje te elementy ktore juz zostaly policzone
vector<int> wartosciUnikalne;
// Sprawdza, czy element jest juz w wektorze wartosciUnikalne
bool czyJest = find(wartosciUnikalne.begin(), wartosciUnikalne.end(), 1) != wartosciUnikalne.end();
// Sprawdza czy wypisano juz 10 kolorow
int ileKolorow = 0;
cout << "Kody szesnastkowe 10 najpopularniejszych kolorow w bitmapie: to" << endl;
// Bedziemy wyliczac wystepowania 10 najczesciej powtarzajaych sie elementow
for (int ilosc = 0; ilosc < 10; ilosc++)
{
int max_count = 0;
for (int i = 0; i < szerokosc*wysokosc; i++)
{
// Sprawdza czy element jest w wartosciUnikalne
czyJest = find(wartosciUnikalne.begin(), wartosciUnikalne.end(), mapaPixeli[i]) != wartosciUnikalne.end();
int count = 1;
// Jesli nie ma elementu w wartosciUnikalne - liczy jego wystapienia
if (czyJest == false)
{
for (int j = i + 1; j<szerokosc*wysokosc; j++)
if (mapaPixeli[i] == mapaPixeli[j])
count++;
if (count>max_count)
max_count = count;
}
}
for (int i = 0; i < szerokosc*wysokosc; i++)
{
int count = 1;
czyJest = find(wartosciUnikalne.begin(), wartosciUnikalne.end(), mapaPixeli[i]) != wartosciUnikalne.end();
// Sprawdza czy jest element w wartosci unikalne, jesli nie ma - szuka aktualnie sprawdzanego elementu o najwiekszej
// ilosci wystapien i wypisuje go
if (czyJest == false)
{
for (int j = i + 1; j < szerokosc*wysokosc; j++)
if (mapaPixeli[i] == mapaPixeli[j])
count++;
if (count == max_count && ileKolorow <=10)
{
ileKolorow++;
wynik = mapaPixeli[i];
cout << hex << wynik << endl;
//cout << count << " " << max_count << endl;
wartosciUnikalne.push_back(wynik);
}
}
}
}
}
else
cout << "Nie udalo sie wczytac bitmapy." << endl;
system("PAUSE");
}
这行:
plik.read((char*)&adresPixeli, sizeof(int));
应该将像素地址写入adresPixeli。 它位于第10个字节,因此在此之前,我只是转到文件的第10个字节:
plik.seekg(10, ios::beg);
在这里,我想将值读入一个名为mapaPixeli的数组,该数组具有足够的内存(宽度*高度)。
for (int i = 0; i < szerokosc * wysokosc; i++)
{
wartoscPixela = 0;
// Wczytujemy 3 bajty - bo na tylu zapisane sa informacje odnosnie 1 pixela, do zmiennej wartoscPixela
plik.read((char*)&wartoscPixela, 3);
// Zapisujemy wartosc w tablicy pixeli
if (iloscBitow == 24)
mapaPixeli[i] = wartoscPixela;
}
问题是:它无法正确读取值:(我不知道为什么,我也找不到错误。也许你们中的一些人可以在那里帮助我。还有一个条件-它只会读取像素(如果是24位)(在我的情况下1像素是24位),请检查它。
然后,有一个我自己的算法,可以在数组中查找10个最流行的值,效果很好,但是在这里却无法如我所愿,因为无法正确读取像素值。
处理位图时,您需要跳过此填充。 我建议替换此循环:
for (int i = 0; i < szerokosc * wysokosc; i++) {
...
}
有两个嵌套循环,并在处理每一行之前在文件中进行搜索:
int wartoscPixela;
int bytesPerPixel = 3;
int padding = szerokosc * bytesPerPixel % 4 == 0 ? 0 : 4 - szerokosc * bytesPerPixel % 4;
for (int i = 0; i < szerokosc; i++)
{
plik.seekg(adresPixeli + (szerokosc*bytesPerPixel+padding)*i, ios::beg);
for (int j = 0; j < wysokosc; j++)
{
wartoscPixela = 0;
// Wczytujemy 3 bajty - bo na tylu zapisane sa informacje odnosnie 1 pixela, do zmiennej wartoscPixela
plik.read((char*)&wartoscPixela, 3);
// Zapisujemy wartosc w tablicy pixeli
if (iloscBitow == 24)
mapaPixeli[i*szerokosc+j] = wartoscPixela;
}
}
在循环之前,您需要计算填充并将其放入变量中:
int padding = szerokosc * bytesPerPixel % 4 == 0 ? 0 : 4 - szerokosc * bytesPerPixel % 4;
然后在每一行之前,将文件流指针移动到每一行的开头:
plik.seekg(adresPixeli + (szerokosc*bytesPerPixel+padding)*i, ios::beg);
此代码假定所讨论的BMP文件每像素3个字节。 如果它的颜色深度不同,则需要相应地修改代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.