-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmrhyde.cpp
More file actions
214 lines (182 loc) · 6.21 KB
/
mrhyde.cpp
File metadata and controls
214 lines (182 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
* mrhyde.cpp
* Copyright (C) 2012 - Giovan Battista Rolandi
* www.glgprograms.it - giomba@live.it
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* Scopo del programma
* Il programma nasconde messaggi di testo in immagini bitmap con profondità
* di colore di 24bpp, ed è in grado di decodificarli successivamente.
*/
#include <fstream> /* flusso su file */
#include <iostream> /* flusso standard */
#include <cmath> /* funzioni matematiche */
using namespace std;
/* Prototipi delle funzioni */
/* Inserisce nella matrice binario[] il carattere passato come argomento in binario */
void byte(unsigned char);
/* Restituisce il carattere ASCII contenuto nella matrice binario[] */
char reverse(void);
/* Legge unsigned int in little-endian dal file passato come argomento e ne restituisce il valore */
unsigned int read32(fstream &); /* Intero a 32bit */
unsigned int read16(fstream &); /* Intero a 16bit */
/* Scrivi sul file indicato, a partire dal byte indicato, un messaggio di cui si conosce la lunghezza */
bool scrivi(fstream&, unsigned int, unsigned int);
/* Legge dal file indicato, a partire dal byte indicato, un messaggio di cui si conosce la lunghezza */
bool leggi(fstream&, unsigned int, unsigned int);
/* Chiede all'utente se si vuole continuare in seguito ad un errore fatale e in caso negativo restituisce true */
bool stop(void);
/* Dichiarazione delle variabili globali */
bool binario[8]; /* Contiene 8 bit per le operazioni di codifica/decodifica */
int main()
{
char nome[256];
clog << "Nome dell'immagine? "; cin.getline(nome, 255);
fstream file(nome, ios::in | ios::out | ios::binary);
if (! file) { cerr << "Impossibile aprire il file '" << nome << "'" << endl; return 1; }
/* Controllo tipo di file */
char imgtype[2];
file.seekg(0, ios::beg); file.read(imgtype, 2);
if (imgtype[0] == 'B' && imgtype[1] == 'M')
{ clog << "File bitmap valido." << endl; }
else
{ cerr << "File bitmap non valido! " << endl; if (stop()) return 1; }
/* Lettura dimensione file */
unsigned int filesize;
file.seekg(2, ios::beg); filesize = read32(file);
clog << "Dimensioni dichiarate: " << filesize << " bytes" << endl;
/* Controllo profondità di colore */
unsigned int depth;
file.seekg(28, ios::beg); depth = read16(file);
if (depth == 24)
{ clog << "Profondità di colore valida: " << depth << "bpp" << endl; }
else
{ cerr << "Profondità di colore non valida: " << depth << "bpp" << endl; if (stop()) return 1; }
/* Lettura spazio disponibile */
unsigned int imgsize, msgsize;
file.seekg(34, ios::beg); imgsize = read32(file);
msgsize = imgsize / 8;
clog << "Bytes utili: " << imgsize << " (circa " << msgsize << " caratteri)" << endl;
/* Lettura start-bit */
unsigned int startbit;
file.seekg(10, ios::beg); startbit = read32(file);
clog << "Startbit dichiarato: " << startbit << endl;
clog << endl;
char scelta[2];
clog << "Scegliere un'operazione: (S)crivi (L)eggi (E)sci" << endl;
cin.getline(scelta, 2);
switch (scelta[0])
{
case 'e': case 'E': break;
case 's': case 'S': scrivi(file, startbit, msgsize); break;
case 'l': case 'L': leggi(file, startbit, msgsize); break;
default: cerr << "Operazione sconosciuta!"; return 1; break;
}
clog << endl << "Programma terminato!" << endl;
return 0;
}
void byte(unsigned char numero)
{
short int v;
for (v = 0; v <= 7; v++)
{ binario[v] = false; }
for (v = 7; v >= 0; v--)
{
binario[v] = (bool) (numero % 2);
numero = (int) numero / 2;
}
}
unsigned int read32(fstream &flusso)
{
char aa, bb, cc, dd; unsigned char a, b, c, d;
flusso.get(aa); flusso.get(bb); flusso.get(cc); flusso.get(dd);
a = aa; b = bb; c = cc; d = dd;
unsigned int numero = 0;
numero = a + b * pow(2, 8) + c * pow(2, 16) + d * pow(2, 24);
return numero;
}
unsigned int read16(fstream &flusso)
{
char aa, bb; unsigned char a, b;
flusso.get(aa); flusso.get(bb);
a = aa; b = bb;
unsigned int numero = 0;
numero = a + b * pow(2, 8);
return numero;
}
bool scrivi(fstream &file, unsigned int startbit, unsigned int msgsize)
{
clog << "Inserire messaggio:" << endl;
char messaggio[msgsize]; cin.getline(messaggio, msgsize);
unsigned char carattere; unsigned int v = 0, n = 0;
char ssample; char sample;
unsigned long int pos = startbit;
file.seekg(startbit, ios::beg); file.seekp(startbit, ios::beg);
while (1)
{
carattere = messaggio[v]; v++;
byte(carattere);
for (n = 0; n <= 7; n++)
{
file.seekg(pos, ios::beg);
file.get(ssample); sample = ssample;
if ((sample % 2) == 0)
{ if (binario[n] != 0) { sample++; } }
else
{ if (binario[n] != 1) { sample--; } }
file.seekp(pos, ios::beg); file.put(sample);
pos++;
}
if (carattere == '\0') break;
}
clog << "Messaggio salvato!" << endl;
return true;
}
bool leggi(fstream &file, unsigned int startbit, unsigned int msgsize)
{
clog << "Decodifica:" << endl;
unsigned int v, n; char carattere, c;
file.seekg(startbit, ios::beg);
for (v = 0; v < msgsize; v++)
{
for (n = 0; n <= 7; n++)
{
file.get(carattere); binario[n] = carattere % 2;
}
c = reverse();
if (c == 0) break;
cout << c;
}
return true;
}
char reverse(void)
{
short int v; char ascii = 0;
for (v = 0; v <= 7; v++)
{
ascii = ascii + binario[v] * pow(2, 7 - v);
}
return ascii;
}
bool stop(void)
{
char scelta[2];
cerr << "Errore fatale. Continuare comunque? (s/N)" << endl;
cin.getline(scelta, 2);
if (scelta[0] == 's' || scelta[0] == 'S') return false;
else return true;
}