dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Sailian
Użytkownik
Użytkownik
Posty: 16
Rejestracja: 17 paź 2007, o 21:33
Płeć: Mężczyzna
Lokalizacja: Wrocław

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: Sailian »

Witam, mam dzisiaj następujący problem:

mam napisać program wczytujący bitmapę 24bit, przeanalizować ją i rozdzielić na składowe RGB, a nastepnie zapisac jako 3 osobne pliki R,G,B

odrazu mówię google mnie nie pogryzło, szukałem
i znalazłem składowe zapisu pliku bmp na tej stronie


składowe:
bfType, bfSize, bfReserved, bfReserved2, bfOffBits, biSize, biWidth, biHeight, biPlanes, biBitConnt, biClrUsed, biClrImportant

niestety nie znam aż na tyle dobrze języka c++, żebym sobie z tym sam poradził, wiem ze bity sa zapisywane w pewnej kolejności, i nalezało by je tak odczytać

mam pomysł żeby stworzyć 3 pętle gdzie plik zostanie zanalizowany i zostaną wyzerowane wartości

tj powiedzmy piksel(123,123,123); R,G,B -> czerwony(123,0,0);

a następnie zostanie wczytany do tablicy -> tabczerwony[n] = czerwony(123,0,0)


powiedzcie mi czy dobrze myslę ?

bardzo prosze o programy pomocnicze,
w roli jasnosci nie chcę żeby ktoś to napisał za mnie, po prostu pokażcie mi jakieś przykłady które by mnie nakierowały trochę na to jak to napisać.
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: soku11 »

Analizujesz normalnie jak każdy plik binarny. Otwierasz w trybie binarnym i czytasz. Najpierw masz nagłówek, więc wczytujesz kolejne jego elementy, czyli te bf... I można od razu ten nagłówek wpisać do plików r.bmp, b.bmp, g.bmp będącymi plikami binarnymi wyjściowymi. I teraz po nagłówku masz dane w formacie BGR (ilość danych odczytujesz z nagłówka). Czyli czytasz jeden bajt (unsigned char) i masz niebieski, następnie kolejny i masz zielony i na końcu dostajesz czerwony. Teraz do odpowiednich plików wpisujesz poszczególne składowe z wyzerowanymi innymi kolorami. I tyle. Warto tylko pamiętać, o wyrównaniu do 4.

Pozdrawiam.
Sailian
Użytkownik
Użytkownik
Posty: 16
Rejestracja: 17 paź 2007, o 21:33
Płeć: Mężczyzna
Lokalizacja: Wrocław

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: Sailian »

rozumiem

ale prosze o przykłady, i cześci kodów.
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: soku11 »

Jakie przykłady? Kodów na necie jest zapewne od groma odnośnie wczytywanie bitmap...

Pozdrawiam.
Sailian
Użytkownik
Użytkownik
Posty: 16
Rejestracja: 17 paź 2007, o 21:33
Płeć: Mężczyzna
Lokalizacja: Wrocław

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: Sailian »

przykłady np jak analizować plik, tak google mnie nie pogryzło znalazłem składowe, ale teraz nie wiem jak je zainicjować, ani jak przeanalizować plik, jestem słaby z c++ więc proszę o PRZYKŁADY,

konkretniej mówiąc wycinki kodów opisując do czego służą i dlaczego właśnie w taki sposób sa zainicjowany a nie inny.
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: soku11 »

Analiza pliku -> std::ifstream + metoda read/get
Inicjować - sprawdź może co znaczy to słowo
Jak ustalać wartości poszczególnych pól? Bardzo prosto: wczytujesz daną z pliku do zmiennej.

Plik jest liniowym obszarem pamięci, tak więc przechodzisz po nim krok po kroku prawie jak po tablicy Kodów nie będę ci szukał, bo to naprawdę nie problem. Nie wiesz jak wczytywać plik: wpisz binary file c++, itd...
Pozdrawiam.
Sailian
Użytkownik
Użytkownik
Posty: 16
Rejestracja: 17 paź 2007, o 21:33
Płeć: Mężczyzna
Lokalizacja: Wrocław

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: Sailian »

zdecydowałem się na uzycie #include <fstream>

pytałem kolegę, i nie rozumiem jednej funkcji

a konkretnie przy wczytywaniu pliku


ifstream wczytaj(nazwa_pliku.c_str(), ios::binary);


do czego służy funkcja *.c_str()

bo jej po prostu nie rozumiem ? szukałem w google, wiki, yahoo, i jedyne co otrzymałem że dane są odczytywane jako const char i nie mogą zostać przeanalizowane, a czy ktoś mógłby mi tak bardziej po ludzku wytłumaczyć do czego to służy ?
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: soku11 »

Dlatego to jest użyte, bo konstruktor obiektu std::ifstream oczekuje nazwy pliku w konwencji C, czyli C-stringu (const char*), czyli wskaźniku na stały ciąg znaków. U ciebie zmienna nazwa_pliku jest typu std::string. Nie można więc go podać jako argument. Ale klasa std::string to nic innego jak "nakładka" na C-stringa, który się sam poszerza. Ma więc w sobie gdzieś zaallokowaną tablicę właśnie w konwencji C. Ta metoda zwraca na nią wskaźnik. Dlaczego stały? Żeby nie modyfikować wnętrzności obiektu.

Tak w ogóle, to widzę, że chcesz sklecić jakiś kod z gotowców, skoro nie rozumiesz tego co piszesz... Powodzenia życzę
Pozdrawiam.
Sailian
Użytkownik
Użytkownik
Posty: 16
Rejestracja: 17 paź 2007, o 21:33
Płeć: Mężczyzna
Lokalizacja: Wrocław

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: Sailian »

Tak rozwiązałem swój problem. znalazłem bardzo fajnego tutoriala z c++ gdzie bardzo ładnie były opisane takie funkcje jak getc, nawet spodobała mi się ta funkcja.


teraz pytanko: o chociażby tu:
fseek(plik, 0, SEEK_SET);
if(feof(plik))
{
cout<<"jestes po za bitami pliku";
getch();
return 0;
}
else
{
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
iloscbitow = getc(plik);
cout<<"wartosc bitu to: "<<iloscbitow<<endl;
cout<<"teraz nastapi skopiowanie naglowka do tablicy naglowkowej"<<endl;
getch();
}
fseek(plik, 0, SEEK_SET);
while(i!=0)
{
naglowek=getc(plik);
cout<<naglowek<<" ";
i--;
}

używam feof, żeby sprawdzić czy nie znajduję się po za bitami pliku
ale nawet gdy sam swiadomie ustawiam fseek po za bitami pliku, petla nie działa dlaczego ?


oto cały kod, nie chciało mi się czyścić, a niektóre zmienne sa wywołane ale nie używane, jak np biWidth, biHeight.
ogólne działanie programu oparłem tylko i wyłącznie na bitach pliku
od 54 sprawdziłem ile plik ma długosci, i przekopiowałem resztę i rozdzieliłem

problem pojawia się gdy używam pliku o rozdzielczosci wyższej niż 249x249
program działa ale nie rozdziela poprawnie obrazka dlaczego ?

#include <iostream>
#include <conio.h>

using namespace std;

int main()
{
FILE *plik;
long miejsce;
int biWidth;
int biHeight;
int bfSize;
int naglowek[54];
int wartoscbitow;
int iloscbitow;
int i=54;
plik = fopen("c:\bmp3.bmp","rb");

fseek(plik, 0, SEEK_SET);
if(feof(plik))
{
cout<<"jestes po za bitami pliku";
getch();
return 0;
}
else
{
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
iloscbitow = getc(plik);
cout<<"wartosc bitu to: "<<iloscbitow<<endl;
cout<<"teraz nastapi skopiowanie naglowka do tablicy naglowkowej"<<endl;
getch();
}
fseek(plik, 0, SEEK_SET);
while(i!=0)
{
naglowek=getc(plik);
cout<<naglowek<<" ";
i--;
}
cout<<" "<<endl;
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
getch();
fseek(plik, 2, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
bfSize = getc(plik);
cout<<"dlugosc pliku w bajtach to: "<<bfSize<<endl;

fseek(plik, 18, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
biWidth = getc(plik);
cout<<"szerokosc rysunku to: "<<biWidth<<endl;

fseek(plik, 22, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
biHeight = getc(plik);
cout<<"wysokosc rysunku to: "<<biHeight<<endl;

fseek(plik, 54, SEEK_SET);
if(feof(plik))
{
cout<<"jestes po za bitami pliku";
getch();
return 0;
}
else
{
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
iloscbitow = getc(plik);
cout<<"wartosc bitu to: "<<iloscbitow<<endl;
cout<<"teraz nastapi rozdzielenie bitow do osobnych plikow";
getch();
}
i=0;
fseek(plik, 0, SEEK_END);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
wartoscbitow = getc(plik);
cout<<"wartosc ostatniego bitu to: "<<wartoscbitow<<endl;

i = miejsce;
iloscbitow = i;
int tabred;
int tabgreen;
int tabblue;

cout<<i;
while(i!=0)
{
tabred=0;
tabgreen=0;
tabblue=0;
i--;
}
i = miejsce;
fseek(plik,54,SEEK_SET);
while(i!=0)
{
tabblue[i]=getc(plik);
cout<<tabblue[i]<<" ";
i--;
tabgreen[i]=getc(plik);
cout<<tabgreen[i]<<" ";
i--;
tabred[i]=getc(plik);
cout<<tabred[i]<<" ";
i--;
}

miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku bluebmp3.bmp"<<endl;
getch();
plik = fopen("c:\bluebmp3.bmp","wb");
i=miejsce;
int stala_miejsce = miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabblue[i], plik);
cout<<tabblue[i]<<" ";
i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku bluebmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
cout<<naglowek[i]<<" ";
i--;
}

getch();
fclose(plik);

plik = fopen("c:\greenbmp3.bmp","wb");
miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku grenbmp3.bmp"<<endl;
getch();
plik = fopen("c:\greenbmp3.bmp","wb");
i=stala_miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabgreen[i], plik);
cout<<tabgreen[i]<<" ";
i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku greenbmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
cout<<naglowek[i]<<" ";
i--;
}
getch();
fclose(plik);

plik = fopen("c:\redbmp3.bmp","wb");

miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku redbmp3.bmp"<<endl;
getch();
plik = fopen("c:\redbmp3.bmp","wb");
i=stala_miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabred[i], plik);
cout<<tabred[i]<<" ";
i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku redbmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
cout<<naglowek[i]<<" ";
i--;
}
getch();
fclose(plik);
cout<<endl<<"KONIEC PROGRAMU PLIKI ZOSTALY ZAPISANE W KATALOGU C: ";
getch();
return 0;
}

-- 16 stycznia 2010, 10:04 --

prosze o uwagi dotyczące kodu.-- 17 stycznia 2010, 15:49 --poprawiony kod, dalej prosze o komentarze


#include <iostream>
#include <conio.h>

using namespace std;

int main()
{
FILE *plik;

int miejsce;
int biWidth;
int biHeight;
int bfSize;
char naglowek[54];
int wartoscbitow;
int iloscbitow;
int i=54;
plik = fopen("c:\bmp3.bmp","rb");

fseek(plik, 0, SEEK_SET);
if(feof(plik))
{
cout<<"jestes po za bitami pliku";
getch();
return 0;
}
else
{
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
iloscbitow = getc(plik);
cout<<"wartosc bitu to: "<<iloscbitow<<endl;
cout<<"teraz nastapi skopiowanie naglowka do tablicy naglowkowej"<<endl;
getch();
}
fseek(plik, 0, SEEK_SET);
while(i!=0)
{
naglowek[i]=getc(plik);
cout<<naglowek[i]<<" ";
i--;
}
cout<<" "<<endl;
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
getch();
fseek(plik, 2, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
bfSize = getc(plik);
cout<<"dlugosc pliku w bajtach to: "<<bfSize<<endl;

fseek(plik, 18, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
biWidth = getc(plik);
cout<<"szerokosc rysunku to: "<<biWidth<<endl;

fseek(plik, 22, SEEK_SET);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
biHeight = getc(plik);
cout<<"wysokosc rysunku to: "<<biHeight<<endl;

fseek(plik, 54, SEEK_SET);
if(feof(plik))
{
cout<<"jestes po za bitami pliku";
getch();
return 0;
}
else
{
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
iloscbitow = getc(plik);
cout<<"wartosc bitu to: "<<iloscbitow<<endl;
cout<<"teraz nastapi rozdzielenie bitow do osobnych plikow";
getch();
}
i=0;
fseek(plik, 0, SEEK_END);
miejsce = ftell(plik);
cout<<"jestes na "<<miejsce<<" bicie"<<endl;
wartoscbitow = getc(plik);
cout<<"wartosc ostatniego bitu to: "<<wartoscbitow<<endl;

i = miejsce;
iloscbitow = i;
char tabred[i];
char tabgreen[i];
char tabblue[i];

cout<<i;
while(i!=0)
{
tabred[i]=0;
tabgreen[i]=0;
tabblue[i]=0;
i--;
}
i = miejsce;
fseek(plik,54,SEEK_SET);
while(i!=0)
{
tabblue[i]=getc(plik);

i--;
tabgreen[i]=getc(plik);

i--;
tabred[i]=getc(plik);

i--;
}

miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku bluebmp3.bmp"<<endl;
getch();
plik = fopen("c:\bluebmp3.bmp","wb");
i=miejsce;
int stala_miejsce = miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabblue[i], plik);
i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku bluebmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
i--;
}

getch();
fclose(plik);

plik = fopen("c:\greenbmp3.bmp","wb");
miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku grenbmp3.bmp"<<endl;
getch();
plik = fopen("c:\greenbmp3.bmp","wb");
i=stala_miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabgreen[i], plik);

i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku greenbmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
i--;
}
getch();
fclose(plik);

plik = fopen("c:\redbmp3.bmp","wb");

miejsce=ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
fclose(plik);
cout<<"teraz nastapi wpisanie danych do pliku redbmp3.bmp"<<endl;
getch();
plik = fopen("c:\redbmp3.bmp","wb");
i=stala_miejsce;
fseek(plik, 54, SEEK_SET);
while(i!=0)
{
fputc(tabred[i], plik);
i--;
}
fseek(plik, 0, SEEK_SET);
miejsce = ftell(plik);
cout<<endl<<"jestes na "<<miejsce<<" bicie"<<endl;
cout<<"nastapi wpisanie naglowka do pliku redbmp3.bmp"<<endl;
i=54;
while(i!=0)
{
fputc(naglowek[i],plik);
i--;
}
getch();
fclose(plik);
cout<<endl<<"KONIEC PROGRAMU PLIKI ZOSTALY ZAPISANE W KATALOGU C: ";
getch();
return 0;
}
soku11
Użytkownik
Użytkownik
Posty: 6607
Rejestracja: 16 sty 2007, o 19:42
Płeć: Mężczyzna
Podziękował: 119 razy
Pomógł: 1823 razy

dev c++ wczytać plik bmp 24bit i rozdzielić na składowe RGB

Post autor: soku11 »

Nikt ci tego nie przeczyta:
- wrzuć to w odpowiedni znacznik

Kod: Zaznacz cały

[code]
[/code]
- sformatuj odpowiednio ten kod
- podziel to jakoś sensownie chociaż na jakieś funkcje
- od sprawdzania błędów jest debugger
- powinieneś przedstawić niedziałający fragment kodu, a nie jego całość; nikt nie będzie wiedział o co w nim chodzi oprócz ciebie

A co do problemu z rozdzielczością, to pewnie nie bierzesz pod uwagę wyrównania do 4. I w ogóle, to pracujesz na bajtach, a nie na bitach...
Dodatkowo:

Kod: Zaznacz cały

fseek(plik, 0, SEEK_SET);
if(feof(plik))
Tutaj ten warunek nigdy nie zajdzie. Ustawiasz się na początek pliku i sprawdzasz, czy nie jesteś na końcu. Bezsens...
I to:

Kod: Zaznacz cały

iloscbitow = getc(plik);
To nie sprawdza ilości bitów, ani nawet bajtów. To pobiera znak z aktualnej pozycji pliku. To nie jest jego rozmiar...


Pozdrawiam.
ODPOWIEDZ