Czy ktoś by mógł mi przybliżyć sposób na wykrywanie białych plam obraznie czarno-białym (odcienie szarości) 8-bitowym obrazie BMP. Z góry dzięki za wszelkie pomysły wskazówki.
przejedź po pikselach obrazka za pomocą ScanLine, i sprawdzaj:
if (piksel==clWhite)
{
//tu na przykład zapisuj współrzędne piksela w jakiejś tablicy
}
jednak zrobiłem bez scanaline: każdą wartość piksela koloru białego zamieniam na inny kolor. Czemu tak jest ze na jednym obrazie dobrze zamienia a na drugim biały kolor zmieniony jest na inny, ale tez mieści się w 8-bitach szarości?
Przedstaw swój kod, to zobaczymy :)
int R;
TColor k;
for(int x=0;x<Image2->Picture->Bitmap->Width;x++)
{
for(int y=0;y<Image2->Picture->Bitmap->Height;y++)
{
k = Image2->Picture->Bitmap->Canvas->Pixels[x][y];
R=GetRValue(k);
if (R == clWhite)
{
R == clRed;
Image2->Picture->Bitmap->Canvas->Pixels[x][y]= R;
}
else
Image2->Picture->Bitmap->Canvas->Pixels[x][y]= R;
}
}
wiem że to taki prostacki sposób no ale :) Może trzeba poprzesuwać jakoś bity w obrazie - nie wiem
Powodzenia
Zamiast porównywać do nasycenia koloru czerwonego, porównuj do całego koloru:
TColor k;
for(int x=0;x<Image2->Picture->Bitmap->Width;x++)
for(int y=0;y<Image2->Picture->Bitmap->Height;y++)
{
k = Image2->Picture->Bitmap->Canvas->Pixels[x][y];
Image2->Picture->Bitmap->Canvas->Pixels[x][y]=(k==clWhite) ? clRed : k;
}
no niestety jest tak samo
Spróbuj jeszcze na początku przekąwertować bitmapę na 24-bitową:
Image2->Picture->Bitmap->PixelFormat =pf24bit;
Innych pomysłów nie mam!
no to gratuluje świetnego pomysłu działa :)
A może powiesz czemu to działa ?
Zapewne wcześniej białe plamy były zamieniane na jakiś tam odcień szarości, ponieważ cała bitmapa mogła się składać tylko z takich. Dlatego wystarczyło przestawić z monochromatycznej na pełno kolorową (24bity=3bajty - czerwony, zielony, niebieski). Wcześniej czerwonego koloru piksel nie miał prawa uzyskać - dlatego.
Więcej na ten temat dowiesz się tu
Najwydajniejszym rozwiązaniem, za to troszke skomplikowanym byłoby odczytanie pliku BMP jako pliku binarnego, przeszukanie paletyw celu w odnalezienia indexu koloru białego i znalezienie tegoż koloru w danych obrazowych.
Gosc napisał(a)
Najwydajniejszym rozwiązaniem, za to troszke skomplikowanym byłoby odczytanie pliku BMP jako pliku binarnego, przeszukanie paletyw celu w odnalezienia indexu koloru białego i znalezienie tegoż koloru w danych obrazowych.
Lepszym, ale nie najlepszym. Tym sposobem trzebaby czytać polik z dysku, co spowalnia proces, lub wczytywać plik do pamięci 2 razy. Najlepszym sposobem byłaby funkcja ScanLine:
TColor k;
Bitmapa->PixelFormat =pf24bit; //Ustawiam format pixeli na 24 bitowy
for ( unsigned y = 0; y<Bitmapa->Height; y++)
{
char* p = (char*)Bitmapa->ScanLine[y];
for ( unsigned x = 0; x<Bitmapa->Width; x++)
{
k=p[x];
p[x]=(k==clWhite) ? clRed : k;
}
}
Jest prostszy sposób. Nie trzeba sie bawić w czytanie pikseli. Wystarczy ustawić własność bitmapy TransparentColor na biały i namalować ją czerwonym prostokącie.
adf88 napisał(a)
Jest prostszy sposób. Nie trzeba sie bawić w czytanie pikseli. Wystarczy ustawić własność bitmapy TransparentColor na biały i namalować ją czerwonym prostokącie.
taaa, a po zapisaniu obrazka bitmapa będzie taka sama. Aleś pomysłowy!
Ale ja przepraszam, czegoś nie rozumiem... czy my mówimy o 8-bitowym obrazie bmp? takim z paletą? Takim z paletą, która dla każdego koloru definiuje składowe rgb, a później dane obrazu zawierają tylko indeksy kolorów?
No ale jakie Scanline, jakie czytanie pikseli, panowie...
- otworzyć jako binarny
- skoczyć w offset 0x36, załadować paletę do tablicy char colors[256][3]
- znaleźć indeks, dla którego r,g,b ==255. Zmienić r,g,b na taką wartość, jaką się chce
- i zapisać paletę z powrotem (a co tam paletę! 3 bajty zapisać, te które się zmieniło!).
W BITMAPINFO są 4 bajty na kolor, tamto z 3 było chyba win 3.1, z 40 lat temu.
char* p = (char*)Bitmapa->ScanLine[y];
for ( unsigned x = 0; x<Bitmapa->Width; x++)
{
k=p[x];
p[x]=(k==clWhite) ? clRed : k;
}
wstawiłeś 3 bajty na kolor to musisz skakać co 3: x += 3,
k = p[x]; // jeden bajt
warunek:
k == clWhite będzie zawsze fałszywy, bo clWhite = 0xffffff, a k <= 0xff
jeśli nawet mogłoby to działać to po co to k?
if( p[x] == clWhite ) p[x] = clRed;
JaskMar napisał(a)
adf88 napisał(a)
Jest prostszy sposób. Nie trzeba sie bawić w czytanie pikseli. Wystarczy ustawić własność bitmapy TransparentColor na biały i namalować ją czerwonym prostokącie.
taaa, a po zapisaniu obrazka bitmapa będzie taka sama. Aleś pomysłowy!
taaa, a po zapisaniu tego co namalowaliśmy będzie co potrzba. Aleś bystry !
Z utworzeniem nowej palety też dobry pomysł. Ale nie zapomnij, najpierw trzeba konwertować z 8 bitów bez palety na 24bity z paletą.
Ranides napisał(a)
Ale ja przepraszam, czegoś nie rozumiem... czy my mówimy o 8-bitowym obrazie bmp? takim z paletą? Takim z paletą, która dla każdego koloru definiuje składowe rgb, a później dane obrazu zawierają tylko indeksy kolorów?
No ale jakie Scanline, jakie czytanie pikseli, panowie...
- otworzyć jako binarny
- skoczyć w offset 0x36, załadować paletę do tablicy char colors[256][3]
- znaleźć indeks, dla którego r,g,b ==255. Zmienić r,g,b na taką wartość, jaką się chce
- i zapisać paletę z powrotem (a co tam paletę! 3 bajty zapisać, te które się zmieniło!).
Coś Ci się pomyliło- w bitmapie 8-bitowej monochromatycznej nie mamy składowych RGB. Trzeba ją przekonwertować, na 24- bitową, która takie indeksy już posiada. A to w trybie binarnym nie byłoby już takie proste.
badzo napisał(a)
W BITMAPINFO są 4 bajty na kolor, tamto z 3 było chyba win 3.1, z 40 lat temu.
Można sobie to przestawić, żeby było łatwiej.
JaskMar napisał(a)
Coś Ci się pomyliło- w bitmapie 8-bitowej monochromatycznej nie mamy składowych RGB. Trzeba ją przekonwertować, na 24- bitową, która takie indeksy już posiada. A to w trybie binarnym nie byłoby już takie proste.
Jeszcze się nie spotkałem, z takim czymś jak 8 bitowa bitmapa monochromatyczna, albo 24 bitowa posiadająca paletę. Jeżeli bitmapa jest 8 bitowa, musi zawierać paletę.
Nie mniej polecam się zapoznać z formatem BMP, zamiast pisać takie bzdury.
Sposób Ranides'a jest najlepszym i najszybszym rozwiązaniem.
Gość napisał(a)
Jeszcze się nie spotkałem, z takim czymś jak 8 bitowa bitmapa monochromatyczna, albo 24 bitowa posiadająca paletę. Jeżeli bitmapa jest 8 bitowa, musi zawierać paletę.
Nie mniej polecam się zapoznać z formatem BMP, zamiast pisać takie bzdury.
Sposób Ranides'a jest najlepszym i najszybszym rozwiązaniem.
Składowe RGB to nie jest to samo co paleta kolorów! Istnieje zarówno bitmapa 8-bitowa, która posiada 256 różnych kolorów, jak i taka, która ma 256 odcieni szarości. A to, że nie spotkałeś się z 24-bitową, posiadającą paletę kolorów - to dopiero bzdura!
Zwracam honor w jednej sprawie - pomyliła mi się monochromatyczna (czyli dwukolorowa) z odcieniami szarości.
JaskMar napisał(a)
A to, że nie spotkałeś się z 24-bitową, posiadającą paletę kolorów - to dopiero bzdura!
Tylko powiedz po co paleta w bitmapie 24 bitowej? :>
0x666 napisał(a)
JaskMar napisał(a)
A to, że nie spotkałeś się z 24-bitową, posiadającą paletę kolorów - to dopiero bzdura!
Tylko powiedz po co paleta w bitmapie 24 bitowej? :>
Np. paleta 2^24 kolorów formatu R32G32B32 :-P
adf88 napisał(a)
0x666 napisał(a)
JaskMar napisał(a)
A to, że nie spotkałeś się z 24-bitową, posiadającą paletę kolorów - to dopiero bzdura!
Tylko powiedz po co paleta w bitmapie 24 bitowej? :>
Np. paleta 2^24 kolorów formatu R32G32B32 :-P
Rozmawiajmy o standardzie BMP, a nie jakiś egzotycznych odmianach. Jak wcześniej powtórzyłem polecam się zapoznać ze standardem BMP, a szczególnie fragmentem dot. palety: http://en.wikipedia.org/wiki/Windows_and_OS/2_bitmap#Color_palette
Gosc napisał(a)
adf88 napisał(a)
Np. paleta 2^24 kolorów formatu R32G32B32 :-P
Rozmawiajmy o standardzie BMP, a nie jakiś egzotycznych odmianach.
Hehe przecież to był żart. Wystarczy sobie policzyć ile taka paleta ważyłaby dla całej 24-bitowej gamy kolorów ;-)
Przecież ta paleta nie jest zapisywana w pliku. Liczy ona sobie 224 kolorów, czyli tyle, ile jest w stanie wyświetlić zwykły monitor. W pliku jest tylko zapisane, że właśnie takiej palety się używa. To wszystko.
Przecież to nielogiczne. Taka paleta ważyłaby ~50MB, a 24-bitowy indeks miałby tą samą wartość co kolor w palecie, na który wskazuje.
Dokładnie 48MB :-p , ale wyobraź sobie, że zamiast zapisywać paletę, można zapisać prosty algorytm, który dowolny dowolny kolor znajdzie. W Borlandowskoch IDE taki algorytm kryje się pod funkcją RGB(). Powtarzam - kolory, składające się z indeksów RGB, gdzie każdy z nich przyjmuje wartości 0-255, to również konkretna paleta kolorów.
Przecież można by wymyślić paletę, która dla RGB przyjmowałaby wartości 0-65536. A że większość monitorów nie będzie w stanie jej wyświetlić - jego strata
JaskMar napisał(a)
W Borlandowskoch IDE taki algorytm kryje się pod funkcją RGB().
:-D To NIE jest funkcja tylko makro z pliku wingdi.h:
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
JaskMar napisał(a)
Powtarzam - kolory, składające się z indeksów RGB, gdzie każdy z nich przyjmuje wartości 0-255, to również konkretna paleta kolorów.
Po pierwsze, to nie są indeksy tylko odcienie poszczególnych składowych koloru. Po drugie zaczynasz kombinować - mówimy tu o palecie jako tablicy z możliwymi kolorami, a nie o tym, że RGB może opisywać pewną paletę kolorów (z określoną rozdzielczością).
W 24 bitowych bitmapach piksel opisany jest w 3 bajtach, które zawierają info o intensywności składowych R, G i B. Żadne tam indeksy [!!!]
JaskMar: dyskusje na modłę greckich filozofów moglibyśmy do usranej śmierci prowadzić. Zamiast więc tworzyć jakieś wyimaginowane wizje, wziąłem bitmapę 480x360, zamieniłem na grayscale i sprawdziłem rozmiar pliku (bo więcej mi się nie chciało).
Rozmiar pliku rzeczywisty: 173 878
Z czego:
172 800 danych obrazu
1 078 danych nagłówkowych
Jak nagłówek zajmuje ponad KB, to oczywiste, że jest tam chyba "coś" więcej, niż sygnatura pliku :] Owe "coś", to nie zgadniesz: paleta zajmująca 1024 bajty. Zostaje 54 bajty. I znowu niespodzianka:
podpina się to pod wzór dla bitmapy z paletą:
gdzie n to ilość bitów na piksel (n=8).
A co do twoich wywodów:
tak, wiesz, ja sobie mogę stworzyć "bitmapę" co będzie miała 5 kanałów w dwóch bajtach:
2: R
3: G
2: B
1: przeźroczystość
8: położenie na osi Z
i co z tego? Po cholerę coś wymyślasz? Takich dziwactw nie ma. To już nie standardowa bitmapa. To twoje własne widzimisię i nikomu nie wmówisz, że jest inaczej. Nie ma co kombinować, tylko powiedzieć jasno, że się machnąłeś.
Też się machnąłem, bo z pamięci rzuciłem, że mamy 3 bajty na kolor, a domyślnie przypada 4 bajty (ten czwarty nieużywany zazwyczaj).
IMHO EOT, bo w następnych postach mogę się co najwyżej powtarzać - tutaj zostało empirycznie pokazane, że nie ma takich cudów, jak grayscalowa bitmapa bez palety.
Jak zwał, tak zwał, może i nie indeksy, tylko odcienie, a może nasycenie... kij wie, to tylko nazwa.
Co za różnica, czy makro, czy funkcja. Równie dobrze to makro można przedstawić w postaci funkcji.
A po drugie - każdy plik BMP ma paletę. Tylko niektóre z nich mają ją zapisaną w pliku całą (PixelFormat=pfCostum), a inne, które posługują się paletami standardowymi, jak np. 24 bity, RGB, lub 1 bit biało-czarny, mają tylko zapisany stan flagi PixelFormat:
pf1bit
pf4bit
pf8bit
pf15bit
pf16bit
pf24bit
pf32bit
A i machnąłem się. Przez pierwszy post w tym temacie. Ale upieram się - bitmapa 24-bitowa ma paletę, tylko nie zapisaną w pliku.