1 /* 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 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % 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 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/blob.h" 45 #include "MagickCore/blob-private.h" 46 #include "MagickCore/cache.h" 47 #include "MagickCore/colormap.h" 48 #include "MagickCore/constitute.h" 49 #include "MagickCore/exception.h" 50 #include "MagickCore/exception-private.h" 51 #include "MagickCore/image.h" 52 #include "MagickCore/image-private.h" 53 #include "MagickCore/list.h" 54 #include "MagickCore/magick.h" 55 #include "MagickCore/memory_.h" 56 #include "MagickCore/monitor.h" 57 #include "MagickCore/monitor-private.h" 58 #include "MagickCore/pixel-accessor.h" 59 #include "MagickCore/quantum-private.h" 60 #include "MagickCore/static.h" 61 #include "MagickCore/string_.h" 62 #include "MagickCore/module.h" 63 64 /* 66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 67 % % 68 % % 69 % % 70 % R e a d S T E G A N O I m a g e % 71 % % 72 % % 73 % % 74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 % 76 % ReadSTEGANOImage() reads a steganographic image hidden within another 77 % image type. It allocates the memory necessary for the new Image structure 78 % and returns a pointer to the new image. 79 % 80 % The format of the ReadSTEGANOImage method is: 81 % 82 % Image *ReadSTEGANOImage(const ImageInfo *image_info, 83 % ExceptionInfo *exception) 84 % 85 % A description of each parameter follows: 86 % 87 % o image_info: the image info. 88 % 89 % o exception: return any errors or warnings in this structure. 90 % 91 */ 92 static Image *ReadSTEGANOImage(const ImageInfo *image_info, 93 ExceptionInfo *exception) 94 { 95 #define GetBit(alpha,i) (((size_t) (alpha) >> (size_t) (i)) & 0x01) 96 #define SetBit(i,set) SetPixelIndex(image,(Quantum) ((set) != 0 ? \ 97 (size_t) GetPixelIndex(image,q) | (one << (size_t) (i)) : \ 98 (size_t) GetPixelIndex(image,q) & ~(one << (size_t) (i))),q) 99 100 Image 101 *image, 102 *watermark; 103 104 ImageInfo 105 *read_info; 106 107 int 108 c; 109 110 MagickBooleanType 111 status; 112 113 PixelInfo 114 pixel; 115 116 register Quantum 117 *q; 118 119 register ssize_t 120 x; 121 122 size_t 123 depth, 124 one; 125 126 ssize_t 127 i, 128 j, 129 k, 130 y; 131 132 /* 133 Initialize Image structure. 134 */ 135 assert(image_info != (const ImageInfo *) NULL); 136 assert(image_info->signature == MagickCoreSignature); 137 if (image_info->debug != MagickFalse) 138 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 139 image_info->filename); 140 assert(exception != (ExceptionInfo *) NULL); 141 assert(exception->signature == MagickCoreSignature); 142 one=1; 143 image=AcquireImage(image_info,exception); 144 if ((image->columns == 0) || (image->rows == 0)) 145 ThrowReaderException(OptionError,"MustSpecifyImageSize"); 146 read_info=CloneImageInfo(image_info); 147 SetImageInfoBlob(read_info,(void *) NULL,0); 148 *read_info->magick='\0'; 149 watermark=ReadImage(read_info,exception); 150 read_info=DestroyImageInfo(read_info); 151 if (watermark == (Image *) NULL) 152 return((Image *) NULL); 153 watermark->depth=MAGICKCORE_QUANTUM_DEPTH; 154 if (AcquireImageColormap(image,MaxColormapSize,exception) == MagickFalse) 155 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 156 if (image_info->ping != MagickFalse) 157 { 158 (void) CloseBlob(image); 159 return(GetFirstImageInList(image)); 160 } 161 status=SetImageExtent(image,image->columns,image->rows,exception); 162 if (status == MagickFalse) 163 return(DestroyImageList(image)); 164 for (y=0; y < (ssize_t) image->rows; y++) 165 { 166 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 167 if (q == (Quantum *) NULL) 168 break; 169 for (x=0; x < (ssize_t) image->columns; x++) 170 { 171 SetPixelIndex(image,0,q); 172 q+=GetPixelChannels(image); 173 } 174 if (SyncAuthenticPixels(image,exception) == MagickFalse) 175 break; 176 } 177 /* 178 Get hidden watermark from low-order bits of image. 179 */ 180 c=0; 181 i=0; 182 j=0; 183 i=(ssize_t) (watermark->depth-1); 184 depth=watermark->depth; 185 for (k=image->offset; (i >= 0) && (j < (ssize_t) depth); i--) 186 { 187 for (y=0; (y < (ssize_t) image->rows) && (j < (ssize_t) depth); y++) 188 { 189 x=0; 190 for ( ; (x < (ssize_t) image->columns) && (j < (ssize_t) depth); x++) 191 { 192 if ((k/(ssize_t) watermark->columns) >= (ssize_t) watermark->rows) 193 break; 194 (void) GetOneVirtualPixelInfo(watermark,UndefinedVirtualPixelMethod, 195 k % (ssize_t) watermark->columns,k/(ssize_t) watermark->columns, 196 &pixel,exception); 197 q=GetAuthenticPixels(image,x,y,1,1,exception); 198 if (q == (Quantum *) NULL) 199 break; 200 switch (c) 201 { 202 case 0: 203 { 204 SetBit(i,GetBit(pixel.red,j)); 205 break; 206 } 207 case 1: 208 { 209 SetBit(i,GetBit(pixel.green,j)); 210 break; 211 } 212 case 2: 213 { 214 SetBit(i,GetBit(pixel.blue,j)); 215 break; 216 } 217 } 218 if (SyncAuthenticPixels(image,exception) == MagickFalse) 219 break; 220 c++; 221 if (c == 3) 222 c=0; 223 k++; 224 if (k == (ssize_t) (watermark->columns*watermark->columns)) 225 k=0; 226 if (k == image->offset) 227 j++; 228 } 229 } 230 status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,depth); 231 if (status == MagickFalse) 232 break; 233 } 234 watermark=DestroyImage(watermark); 235 (void) SyncImage(image,exception); 236 return(GetFirstImageInList(image)); 237 } 238 239 /* 241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 242 % % 243 % % 244 % % 245 % R e g i s t e r S T E G A N O I m a g e % 246 % % 247 % % 248 % % 249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 250 % 251 % RegisterSTEGANOImage() adds attributes for the STEGANO image format to 252 % the list of supported formats. The attributes include the image format 253 % tag, a method to read and/or write the format, whether the format 254 % supports the saving of more than one frame to the same file or blob, 255 % whether the format supports native in-memory I/O, and a brief 256 % description of the format. 257 % 258 % The format of the RegisterSTEGANOImage method is: 259 % 260 % size_t RegisterSTEGANOImage(void) 261 % 262 */ 263 ModuleExport size_t RegisterSTEGANOImage(void) 264 { 265 MagickInfo 266 *entry; 267 268 entry=AcquireMagickInfo("STEGANO","STEGANO","Steganographic image"); 269 entry->decoder=(DecodeImageHandler *) ReadSTEGANOImage; 270 entry->format_type=ImplicitFormatType; 271 (void) RegisterMagickInfo(entry); 272 return(MagickImageCoderSignature); 273 } 274 275 /* 277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 278 % % 279 % % 280 % % 281 % U n r e g i s t e r S T E G A N O I m a g e % 282 % % 283 % % 284 % % 285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 286 % 287 % UnregisterSTEGANOImage() removes format registrations made by the 288 % STEGANO module from the list of supported formats. 289 % 290 % The format of the UnregisterSTEGANOImage method is: 291 % 292 % UnregisterSTEGANOImage(void) 293 % 294 */ 295 ModuleExport void UnregisterSTEGANOImage(void) 296 { 297 (void) UnregisterMagickInfo("STEGANO"); 298 } 299