繁体   English   中英

C ++-位图的10种最流行的颜色

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM