blob: 2952db7fd03b63ad72fe973bd50a415f30417f6d [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% SSSSS TTTTT EEEEE GGGG AAA N N OOO %
7% SS T E G A A NN N O O %
8% SSS T EEE G GG AAAAA N N N O O %
9% SS T E G G A A N NN O O %
10% SSSSS T EEEEE GGG A A N N OOO %
11% %
12% %
13% Write A Steganographic Image. %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/cache.h"
46#include "magick/constitute.h"
47#include "magick/exception.h"
48#include "magick/exception-private.h"
49#include "magick/image.h"
50#include "magick/image-private.h"
51#include "magick/list.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/quantum-private.h"
57#include "magick/static.h"
58#include "magick/string_.h"
59#include "magick/module.h"
60
61/*
62%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63% %
64% %
65% %
66% R e a d S T E G A N O I m a g e %
67% %
68% %
69% %
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71%
72% ReadSTEGANOImage() reads a steganographic image hidden within another
73% image type. It allocates the memory necessary for the new Image structure
74% and returns a pointer to the new image.
75%
76% The format of the ReadSTEGANOImage method is:
77%
78% Image *ReadSTEGANOImage(const ImageInfo *image_info,
79% ExceptionInfo *exception)
80%
81% A description of each parameter follows:
82%
83% o image_info: the image info.
84%
85% o exception: return any errors or warnings in this structure.
86%
87*/
88
89static inline unsigned long MagickMin(const unsigned long x,
90 const unsigned long y)
91{
92 if (x < y)
93 return(x);
94 return(y);
95}
96
97static Image *ReadSTEGANOImage(const ImageInfo *image_info,
98 ExceptionInfo *exception)
99{
100#define GetBit(alpha,i) MagickMin((((unsigned long) (alpha) >> (unsigned long) \
101 (i)) & 0x01),16)
102#define SetBit(alpha,i,set) (alpha)=(IndexPacket) ((set) != 0 ? \
103 (unsigned long) (alpha) | (1UL << (unsigned long) (i)) : (unsigned long) \
104 (alpha) & ~(1UL << (unsigned long) (i)))
105
106 Image
107 *image,
108 *watermark;
109
110 ImageInfo
111 *read_info;
112
113 long
114 c,
115 i,
116 j,
117 k,
118 y;
119
120 MagickBooleanType
121 status;
122
123 PixelPacket
124 pixel;
125
126 register IndexPacket
127 *indexes;
128
129 register long
130 x;
131
132 register PixelPacket
133 *q;
134
135 unsigned long
136 depth;
137
138 /*
139 Initialize Image structure.
140 */
141 assert(image_info != (const ImageInfo *) NULL);
142 assert(image_info->signature == MagickSignature);
143 if (image_info->debug != MagickFalse)
144 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
145 image_info->filename);
146 assert(exception != (ExceptionInfo *) NULL);
147 assert(exception->signature == MagickSignature);
148 image=AcquireImage(image_info);
149 if ((image->columns == 0) || (image->rows == 0))
150 ThrowReaderException(OptionError,"MustSpecifyImageSize");
151 read_info=CloneImageInfo(image_info);
152 SetImageInfoBlob(read_info,(void *) NULL,0);
153 *read_info->magick='\0';
154 watermark=ReadImage(read_info,exception);
155 read_info=DestroyImageInfo(read_info);
156 if (watermark == (Image *) NULL)
157 return((Image *) NULL);
158 watermark->depth=MAGICKCORE_QUANTUM_DEPTH;
159 if (AcquireImageColormap(image,MaxColormapSize) == MagickFalse)
160 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
161 if (image_info->ping != MagickFalse)
162 {
163 (void) CloseBlob(image);
164 return(GetFirstImageInList(image));
165 }
166 /*
167 Get hidden watermark from low-order bits of image.
168 */
169 c=0;
170 i=0;
171 j=0;
172 i=MAGICKCORE_QUANTUM_DEPTH-1;
173 depth=MAGICKCORE_QUANTUM_DEPTH;
174 for (k=image->offset; (i >= 0) && (j < (long) depth); i--)
175 {
176 for (y=0; (y < (long) image->rows) && (j < (long) depth); y++)
177 {
178 x=0;
179 for (; (x < (long) image->columns) && (j < (long) depth); x++)
180 {
181 if ((k/(long) watermark->columns) >= (long) watermark->rows)
182 break;
183 (void) GetOneVirtualPixel(watermark,k % (long) watermark->columns,
184 k/(long) watermark->columns,&pixel,exception);
185 q=GetAuthenticPixels(image,x,y,1,1,exception);
186 if (q == (PixelPacket *) NULL)
187 break;
188 indexes=GetAuthenticIndexQueue(image);
189 switch (c)
190 {
191 case 0:
192 {
193 SetBit(*indexes,i,GetBit(pixel.red,j));
194 break;
195 }
196 case 1:
197 {
198 SetBit(*indexes,i,GetBit(pixel.green,j));
199 break;
200 }
201 case 2:
202 {
203 SetBit(*indexes,i,GetBit(pixel.blue,j));
204 break;
205 }
206 }
207 if (SyncAuthenticPixels(image,exception) == MagickFalse)
208 break;
209 c++;
210 if (c == 3)
211 c=0;
212 k++;
213 if (k == (long) (watermark->columns*watermark->columns))
214 k=0;
215 if (k == image->offset)
216 j++;
217 }
218 }
219 status=SetImageProgress(image,LoadImagesTag,i,depth);
220 if (status == MagickFalse)
221 break;
222 }
223 watermark=DestroyImage(watermark);
224 (void) SyncImage(image);
225 return(GetFirstImageInList(image));
226}
227
228/*
229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230% %
231% %
232% %
233% R e g i s t e r S T E G A N O I m a g e %
234% %
235% %
236% %
237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238%
239% RegisterSTEGANOImage() adds attributes for the STEGANO image format to
240% the list of supported formats. The attributes include the image format
241% tag, a method to read and/or write the format, whether the format
242% supports the saving of more than one frame to the same file or blob,
243% whether the format supports native in-memory I/O, and a brief
244% description of the format.
245%
246% The format of the RegisterSTEGANOImage method is:
247%
248% unsigned long RegisterSTEGANOImage(void)
249%
250*/
251ModuleExport unsigned long RegisterSTEGANOImage(void)
252{
253 MagickInfo
254 *entry;
255
256 entry=SetMagickInfo("STEGANO");
257 entry->decoder=(DecodeImageHandler *) ReadSTEGANOImage;
258 entry->format_type=ExplicitFormatType;
259 entry->description=ConstantString("Steganographic image");
260 entry->module=ConstantString("STEGANO");
261 (void) RegisterMagickInfo(entry);
262 return(MagickImageCoderSignature);
263}
264
265/*
266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267% %
268% %
269% %
270% U n r e g i s t e r S T E G A N O I m a g e %
271% %
272% %
273% %
274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275%
276% UnregisterSTEGANOImage() removes format registrations made by the
277% STEGANO module from the list of supported formats.
278%
279% The format of the UnregisterSTEGANOImage method is:
280%
281% UnregisterSTEGANOImage(void)
282%
283*/
284ModuleExport void UnregisterSTEGANOImage(void)
285{
286 (void) UnregisterMagickInfo("STEGANO");
287}