Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
sgraphy.cpp
Go to the documentation of this file.
1 /// @file sgraphy.cpp
2 ///
3 /// Defines the entry point for the console application.
4 ///
5 /// This simple stenography application demonstrates how data can be
6 /// manipulated with the alchemy message formatting library.
7 ///
8 /// The program can encode an ascii text message within a bitmap, as well
9 /// as extract the message from a bitmap with an encoded message.
10 ///
11 /// - The input bitmap must use a 32-bit per pixel encoding.
12 /// - The application can encode 1-byte per pixel
13 /// - If the secret message exceeds the limits of the image, it will be truncated.
14 /// - The output message extracted from an image may contain extra spaces
15 /// if the original message did not use the entire space available in the image.
16 ///
17 /// The MIT License(MIT)
18 /// @copyright 2014 Paul M Watt
19 // ****************************************************************************
20 #include "sgraphy.h"
21 #include "bitmap.h"
22 #include <iostream>
23 #include <fstream>
24 #include <sstream>
25 
26 using std::cout;
27 using std::endl;
28 using std::string;
29 using std::stringstream;
30 
31 
32 // Global Varibles ************************************************************
33 
34 bool is_encode = false;
35 string msg_file = "msg.txt";
36 string input_file = "source.bmp";
37 string output_file = "target.bmp";
38 
39 // ****************************************************************************
40 bool ParseCmdParams(int argc, char* argv[])
41 {
42  // The second parameter must be the command switch
43  if (4 == argc)
44  {
45  if (0 != strcmp("-d", argv[1]))
46  {
47  return false;
48  }
49 
50  input_file = argv[2];
51  output_file= argv[3];
52  }
53  else if (5 == argc)
54  {
55  if (0 != strcmp("-e", argv[1]))
56  {
57  return false;
58  }
59 
60  is_encode = true;
61  msg_file = argv[2];
62  input_file = argv[3];
63  output_file= argv[4];
64  }
65  else
66  {
67  return false;
68  }
69 
70  return true;
71 }
72 
73 // ****************************************************************************
74 void PrintHelp()
75 {
76  cout << "\nUsage: sgraphy [-e message_path] [-d] input output\n\n"
77  << "Options:\n"
78  << " -e\t\tEncodes the specified message_path into the input file\n"
79  << " -d\t\tDecodes an embedded message from input, and stores in output\n"
80  << "\n"
81  << " -e and -d are mutually exclusive.\n\n";
82 }
83 
84 // ****************************************************************************
85 string ReadFile(const string& path)
86 {
87  std::ifstream input_file(path);
88 
89  stringstream data;
90  data << input_file.rdbuf();
91 
92  return data.str();
93 }
94 
95 // ****************************************************************************
96 void WriteFile( const string& path,
97  const string& data)
98 {
99  std::ofstream output_file(path);
100  output_file << data;
101 }
102 
103 // ****************************************************************************
104 void weave_data ( Hg::rgba_t& pixel,
105  Hg::byte_t& data)
106 {
107  using Hg::s_data;
108 
109  // The lower two bits of the data byte.
110  const Hg::byte_t k_data_mask = 0x03;
111 
112  s_data value(data);
113 
114  pixel.blue = (pixel.blue & ~k_data_mask)
115  | (value.d0 & k_data_mask);
116  pixel.green = (pixel.green & ~k_data_mask)
117  | (value.d1 & k_data_mask);
118  pixel.red = (pixel.red & ~k_data_mask)
119  | (value.d2 & k_data_mask);
120  pixel.alpha = (pixel.alpha & ~k_data_mask)
121  | (value.d3 & k_data_mask);
122 }
123 
124 // ****************************************************************************
125 void extract_data ( Hg::rgba_t& pixel,
126  Hg::byte_t& data)
127 {
128  using Hg::s_data;
129 
130  // The lower two bits of the data byte.
131  const Hg::byte_t k_data_mask = 0x03;
132 
133  s_data value;
134 
135  value.d0 = (pixel.blue & k_data_mask);
136  value.d1 = (pixel.green & k_data_mask);
137  value.d2 = (pixel.red & k_data_mask);
138  value.d3 = (pixel.alpha & k_data_mask);
139 
140  data = value;
141 }
142 
143 // ****************************************************************************
144 int main(int argc, char* argv[])
145 {
146  if (!ParseCmdParams(argc, argv))
147  {
148  PrintHelp();
149  return 0;
150  }
151 
152  string message = ReadFile(msg_file);
153 
154  sgraph::Bitmap bmp;
155  bmp.Load(input_file);
156 
157  if (is_encode)
158  {
159  bmp.process(message, weave_data);
160  bmp.Store(output_file);
161  }
162  else
163  {
164  bmp.process(message, extract_data);
165  WriteFile(output_file, message);
166  }
167 
168  return 0;
169 }