algorytm.org

Implementacja w C/C++



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Ukrywanie tekstu w bitmapach - Implementacja w C/C++
Ocena użytkownikóww: *****  / 14
SłabyŚwietny
Nadesłany przez Michał Knasiecki, 28 lipca 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

BMP.cpp:
/********************************************************
*							*
* Ukrywanie pliku tekstowego w bitmapie			*
* Program został pobrany ze strony www.algorytm.org	*
* Znajdziesz na niej opis tego algorytmu i wielu innych	*
*							*
* Autor:	Michał Knasiecki			*
*             www.algorytm.org				*
*							*
*********************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

//!Klasa służąca do konwersji liczb i manipulacji na najmłodszym bicie
class Bajt{
public:

	int  Wartosc;
	char Bity[100];

//!Ile bitow ma liczba
	int LiczbaBitow;

//!Zamiana atrybutu na wartość binarną
void Binarnie(void){

	int W;
	int l=0;
	W=Wartosc;

	do{
		if ((W % 2) == 0)
			Bity[LiczbaBitow-l-1]='0';
		else
			Bity[LiczbaBitow-l-1]='1';
		W/=2;
		l++;
	}while (l!=LiczbaBitow);
}

//!Zamiana wartości atrybutu na system dziesiętny
void Dziesietnie(void){

	unsigned long val = 1;
	Wartosc=0;

	for (int l=0;l<LiczbaBitow;l++)
	{
		if (Bity[LiczbaBitow-l-1]=='1')
			Wartosc+= val;
		val *= 2;
	}

	return;
}

//!Utworzenie 32-bitowej liczby z bajtow a,b,c i d
void Zamien(Bajt a,Bajt b, Bajt c, Bajt d){

	a.Binarnie();
	b.Binarnie();
	c.Binarnie();
	d.Binarnie();

	for (int i=0;i<8;i++)
		Bity[i]=d.Bity[i];

	for (int i=0;i<8;i++)
		Bity[i+8]=c.Bity[i];

	for (int i=0;i<8;i++)
		Bity[i+16]=b.Bity[i];

	for (int i=0;i<8;i++)
		Bity[i+24]=a.Bity[i];

return;
}

//!Ustawia wartość najmniej znaczącego bitu na i (0 lub 1)
void UstawBit(char i){

	Binarnie();
	Bity[LiczbaBitow-1]=i;

return;
}


//!Konstruktor (n-liczba bitów na liczbę)
Bajt(int n){
	LiczbaBitow=n;
}

};//!Koniec klasy



//!Klasa opisująca obrazek
class BitMapa{

public:

//!Plik wejściowy
	FILE *Plik;

//!Plik z tekstem do ukrycia
	FILE *Tekst;

//!Offset danych
	int AdresDanych;

//!Liczba bajtów opisujących dane
	int RozmiarDanych;

//!Szerokość obrazka w pikselach
	int Szerokosc;

//Liczba bajtów tekstu
	int RozmiarTekstu;

/*!Metoda wczytująca adres danych, liczbę bitów kolorów, i szerokość 
*/
int WczytajPlik(char NazwaPliku[50]){

	int Znak;

//!Otwórz plik z bitmapą (w trybie binarnym)
	Plik=fopen(NazwaPliku,"rb");
	if (Plik==NULL)
		return(0);

//!Przejdź do 10 bajtu i odczytaj adres obszaru danych (4 bajty
	fseek(Plik,10,SEEK_SET);

//Utworz 4 jednobajtowe liczby
	Bajt *word1=new Bajt(8);
	Bajt *word2=new Bajt(8);
	Bajt *word3=new Bajt(8);
	Bajt *word4=new Bajt(8);

//!Wczytuj 4 kolejne bajty
	Znak=getc(Plik);
	word1->Wartosc=Znak;
	Znak=getc(Plik);
	word2->Wartosc=Znak;
	Znak=getc(Plik);
	word3->Wartosc=Znak;
	Znak=getc(Plik);
	word4->Wartosc=Znak;

//!Utworz 32-bitową liczbę z powyższych bajtów
	Bajt *Dane=new Bajt(32);
	Dane->Zamien(*word1,*word2,*word3,*word4);
	Dane->Dziesietnie();

//!Przypisz otrzymaną wartość zmiennej adresu danych
	AdresDanych=Dane->Wartosc;

//!Przejdz do 18 bajtu i odczytaj szerokosc
	fseek(Plik,18,SEEK_SET);

	Znak=getc(Plik);
	word1->Wartosc=Znak;
	Znak=getc(Plik);
	word2->Wartosc=Znak;
	Znak=getc(Plik);
	word3->Wartosc=Znak;
	Znak=getc(Plik);
	word4->Wartosc=Znak;

	Dane->Zamien(*word1,*word2,*word3,*word4);
	Dane->Dziesietnie();

//!Zapamiętaj wartość w atrybucie
	Szerokosc=Dane->Wartosc;


//!Przejdz do 34 bajtu i odczytaj dlugosc obszaru danych (4 bajty)
	fseek(Plik,34,SEEK_SET);

	Znak=getc(Plik);
	word1->Wartosc=Znak;
	Znak=getc(Plik);
	word2->Wartosc=Znak;
	Znak=getc(Plik);
	word3->Wartosc=Znak;
	Znak=getc(Plik);
	word4->Wartosc=Znak;

//!Utworz 32-bitowa liczbe
	Dane->Zamien(*word1,*word2,*word3,*word4);
	Dane->Dziesietnie();

//!Zapamiętaj rozmiar danych
	RozmiarDanych=Dane->Wartosc;


//!Usuń niepotrzebne już obiekty
	delete word1;
	delete word2;
	delete word3;
	delete word4;
	delete Dane;

return(1);
} //!Koniec metody


//!Destruktor zamyka otwarte pliki
~BitMapa(void){
	fclose(Plik);
	fclose(Tekst);
}


//!Metoda odczytuje z bitmapy tekst i drukuje go na ekranie
void Wypisz(char PlikTekstowy[10]){

	int k=0;
	int Znak;
	int Przeczytane=0;

//!Otwórz plik z tekstem (w trybie tekstowym)
	Tekst=fopen(PlikTekstowy,"wt+");

/*!Na końcu linii znajdują się zera nieznaczące. Może ich być 0, 1, 2 lub 3
jest to reszta z dzielenia szerokości przez 4
*/
	int ZeraNieznaczace = Szerokosc % 4;

//!Na końcu tekstu znajduje się ciąg 8 wyzerowanych bitów
	int Koniec=0;

	Bajt *bajtZnaku=new Bajt(8);
	Bajt *bajtTMP=new Bajt(8);
	int licznikBitow=0;

	fseek(Plik,AdresDanych,SEEK_SET);

	while (k!=RozmiarDanych){
		Znak=getc(Plik);
		Przeczytane++;
		if (Przeczytane<=Szerokosc)
			{
			bajtZnaku->Wartosc=Znak;
			bajtZnaku->Binarnie();
			bajtTMP->Bity[licznikBitow]=bajtZnaku->Bity[7];
			licznikBitow++;

			if (licznikBitow==8)
				{
				licznikBitow=0;
				bajtTMP->Dziesietnie();

//!Jeśli znalazłeś bajt 0 (ciąg 8 wyzerowanych bitów) to jest to koniec ukrytego tekstu
			if (bajtTMP->Wartosc==0) Koniec=1;

			if (Koniec==0)
				fprintf(Tekst,"%c",bajtTMP->Wartosc);
			}
		}

	if (Przeczytane==Szerokosc+ZeraNieznaczace)
		Przeczytane=0;
	k++;
}

//!Usuń obiekty
	delete bajtZnaku;
	delete bajtTMP;

return;
}


//!Metoda tworzy bitmapę z ukrytym tekstem
int Kopiuj(char NowaBitmapa[10],char PlikTekstowy[10]){

//!Bitmapa z ukrytym tekstem
	FILE *DrugiPlik;
	int znak;
	int Koniec=0;
	int k=0;
	int Znak;
	int Przeczytane=0;
	int BitZnaku=0;
	int ZnakTekstu;

//!Zera nieznaczące, jak wyżej
	int ZeraNieznaczace= Szerokosc % 4;

	Bajt *bajt=new Bajt(8);
	Bajt *bajtZnaku=new Bajt(8);

//!Otwórz plik z tekstem (w trybie tekstowym)
	Tekst=fopen(PlikTekstowy,"rt+");

//!Odczytaj jego rozmiar i wróć na początek pliku
	RozmiarTekstu=fseek(Tekst,0L,SEEK_END);
	RozmiarTekstu = ftell(Tekst);
	fseek(Tekst,0L,SEEK_SET);

//!Czy wystarczy pikseli do ukrucia tekstu?
	if ((RozmiarTekstu+1)*8>RozmiarDanych)
		return(0);

//!Utwórz drugą bitmapę w trybie binarnym do zapisu
	DrugiPlik=fopen(NowaBitmapa,"wb");

//!Wróć na początek pierwszej bitmapy
	fseek(Plik,0L,SEEK_SET);

/*!Przepisz nagłówek oryginalnej bitmapy (aż do obszaru danych)
niczego nie zmieniając
*/
	do {
		znak=getc(Plik);
		if (k<AdresDanych)
		putc(znak,DrugiPlik);
		k++;
	} while (k<AdresDanych);

/*!Przepisuj kolejne bajty obszaru danych zmieniając ostatni 
bit każdego koloru
*/
	k=0;
	while (k!=RozmiarDanych){

		if ((BitZnaku==0))
			{

			if (Przeczytane<Szerokosc)
				ZnakTekstu=getc(Tekst);

/*!Jeżeli skończył się plik z tekstem, wstaw do drugiej bitmapy
8 bajtów z wyzerowanym ostatnim bitem (znacznik końca tekstu)
*/

		if (ZnakTekstu==-1)
			{
//!Znacznik końca tekstu
			bajtZnaku->Wartosc=0;
			bajtZnaku->Binarnie();
			}

//!Jeżeli tekst się jeszcze nie skończył, pobierz następny bajt
		else{
			bajtZnaku->Wartosc=ZnakTekstu;
			bajtZnaku->Binarnie();
		}
	}

//!Pobierz bajt z oryginalnej bitmapy
	znak=getc(Plik);
	Przeczytane++;

//!Jeżeli nie wkroczyłeś w obszar zer nieznaczących i tekst się jeszcze nie skończył
	if ((Przeczytane<=Szerokosc)&&Koniec==0)
		{
		bajt->Wartosc=znak;
		bajt->Binarnie();

//!Zmień ostatni bit na kolejnt bit bajtu tekstu
		bajt->UstawBit(bajtZnaku->Bity[BitZnaku]);
		BitZnaku++;

		if (BitZnaku==8)
			{
			BitZnaku=0;
			if (bajtZnaku->Wartosc==0)
			Koniec=1;
			}
		bajt->Dziesietnie();

//!Zapisz zmodyfikowany bajt do nowej bitmapy
		znak=bajt->Wartosc;
		putc(znak,DrugiPlik);
		} else

/*!Jeżeli tekst się już skończył lub wkroczyłeś w obszar zer nieznaczących
to przepisz bajt nie zmieniając go
*/
		putc(znak,DrugiPlik);

		if (Przeczytane==Szerokosc+ZeraNieznaczace)
			Przeczytane=0;

		k++;
	}


//!Usuń obiekty i zamknij zmodyfikowaną bitmapę
	delete bajt;
	delete bajtZnaku;
	fclose(DrugiPlik);

return 1;
}

}; //!Koniec klasy


//-----------------------------------------------

void main(void){

	BitMapa BMP;
	int opcja;
	char BMP1[100];
	char BMP2[100];
	char TXT[100];

	printf("Wybierz opcje\n");
	printf("1- Ukrycie pliku\n2- Odzyskanie pliku\n3 - Koniec\n");

	do
		scanf("%d",&opcja);
	while ((opcja!=1)&&(opcja!=2)&&(opcja!=3));

	if (opcja==3) return;

	if (opcja==1){
		printf("Nazwa pliku z wejsciowym obrazem: ");
		scanf("%s",BMP1);
		printf("Nazwa pliku z wejsciowym tekstem: ");
		scanf("%s",TXT);
		printf("Nazwa pliku z wyjsciowym obrazem: ");
		scanf("%s",BMP2);

		if (BMP.WczytajPlik(BMP1)==0){
			printf("Plik %s nie istnieje\n",BMP1);
			getch();
			exit(0);
			}

		if (BMP.Kopiuj(BMP2,TXT)==0)
			{
			printf("Plik z obrazkiem jest zbyt maly, zeby ukryc tekst\n");
			getch();
			exit(0);
			} else printf("Plik zostal ukryty...\n");
		}else

		{
		printf("Nazwa pliku z wejsciowym obrazem: ");
		scanf("%s",BMP1);
		printf("Nazwa pliku z wyjsciowym tekstem: ");
		scanf("%s",TXT);
		if (BMP.WczytajPlik(BMP1)==0){
			printf("Plik %s nie istnieje\n",BMP1);
			getch();
			exit(0);
		}
		BMP.Wypisz(TXT);
		printf("Plik zostal odzyskany...\n");

	}
printf("\nDowolny klawisz...\n");
getch();
return;
}
Dodaj komentarz