1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % M M AAA SSSSS K K % 7 % MM MM A A SS K K % 8 % M M M AAAAA SSS KKK % 9 % M M A A SS K K % 10 % M M A A SSSSS K K % 11 % % 12 % % 13 % Write Mask File. % 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/attribute.h" 45 #include "MagickCore/blob.h" 46 #include "MagickCore/blob-private.h" 47 #include "MagickCore/constitute.h" 48 #include "MagickCore/enhance.h" 49 #include "MagickCore/exception.h" 50 #include "MagickCore/exception-private.h" 51 #include "MagickCore/list.h" 52 #include "MagickCore/magick.h" 53 #include "MagickCore/memory_.h" 54 #include "MagickCore/monitor.h" 55 #include "MagickCore/monitor-private.h" 56 #include "MagickCore/pixel-accessor.h" 57 #include "MagickCore/quantum-private.h" 58 #include "MagickCore/static.h" 59 #include "MagickCore/string_.h" 60 #include "MagickCore/module.h" 61 62 /* 64 Forward declarations. 65 */ 66 static MagickBooleanType 67 WriteMASKImage(const ImageInfo *,Image *,ExceptionInfo *); 68 69 /* 71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72 % % 73 % % 74 % % 75 % R e a d M A S K I m a g e % 76 % % 77 % % 78 % % 79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80 % 81 % ReadMASKImage returns the image mask associated with the image. 82 % 83 % The format of the ReadMASKImage method is: 84 % 85 % Image *ReadMASKImage(const ImageInfo *image_info, 86 % ExceptionInfo *exception) 87 % 88 % A description of each parameter follows: 89 % 90 % o image_info: the image info. 91 % 92 % o exception: return any errors or warnings in this structure. 93 % 94 */ 95 static Image *ReadMASKImage(const ImageInfo *image_info, 96 ExceptionInfo *exception) 97 { 98 Image 99 *image; 100 101 ImageInfo 102 *read_info; 103 104 /* 105 Initialize Image structure. 106 */ 107 assert(image_info != (const ImageInfo *) NULL); 108 assert(image_info->signature == MagickCoreSignature); 109 if (image_info->debug != MagickFalse) 110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 111 image_info->filename); 112 assert(exception != (ExceptionInfo *) NULL); 113 assert(exception->signature == MagickCoreSignature); 114 read_info=CloneImageInfo(image_info); 115 SetImageInfoBlob(read_info,(void *) NULL,0); 116 (void) CopyMagickString(read_info->magick,"MIFF",MagickPathExtent); 117 image=ReadImage(read_info,exception); 118 read_info=DestroyImageInfo(read_info); 119 if (image != (Image *) NULL) 120 { 121 MagickBooleanType 122 status; 123 124 status=GrayscaleImage(image,image->intensity,exception); 125 if (status == MagickFalse) 126 image=DestroyImage(image); 127 } 128 return(GetFirstImageInList(image)); 129 } 130 131 /* 133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 134 % % 135 % % 136 % % 137 % R e g i s t e r M A S K I m a g e % 138 % % 139 % % 140 % % 141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 142 % 143 % RegisterMASKImage() adds attributes for the MASK image format to 144 % the list of supported formats. The attributes include the image format 145 % tag, a method to read and/or write the format, whether the format 146 % supports the saving of more than one frame to the same file or blob, 147 % whether the format supports native in-memory I/O, and a brief 148 % description of the format. 149 % 150 % The format of the RegisterMASKImage method is: 151 % 152 % size_t RegisterMASKImage(void) 153 % 154 */ 155 ModuleExport size_t RegisterMASKImage(void) 156 { 157 MagickInfo 158 *entry; 159 160 entry=AcquireMagickInfo("MASK","MASK","Image Clip Mask"); 161 entry->decoder=(DecodeImageHandler *) ReadMASKImage; 162 entry->encoder=(EncodeImageHandler *) WriteMASKImage; 163 (void) RegisterMagickInfo(entry); 164 return(MagickImageCoderSignature); 165 } 166 167 /* 169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 170 % % 171 % % 172 % % 173 % U n r e g i s t e r M A S K I m a g e % 174 % % 175 % % 176 % % 177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 178 % 179 % UnregisterMASKImage() removes format registrations made by the 180 % MASK module from the list of supported formats. 181 % 182 % The format of the UnregisterMASKImage method is: 183 % 184 % UnregisterMASKImage(void) 185 % 186 */ 187 ModuleExport void UnregisterMASKImage(void) 188 { 189 (void) UnregisterMagickInfo("MASK"); 190 } 191 192 /* 194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 195 % % 196 % % 197 % % 198 % W r i t e M A S K I m a g e % 199 % % 200 % % 201 % % 202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 203 % 204 % WriteMASKImage() writes an image mask to a file. 205 % 206 % The format of the WriteMASKImage method is: 207 % 208 % MagickBooleanType WriteMASKImage(const ImageInfo *image_info, 209 % Image *image,ExceptionInfo *exception) 210 % 211 % A description of each parameter follows. 212 % 213 % o image_info: the image info. 214 % 215 % o image: The image. 216 % 217 % o exception: return any errors or warnings in this structure. 218 % 219 */ 220 221 static Image *MaskImage(const Image *image,ExceptionInfo *exception) 222 { 223 CacheView 224 *image_view, 225 *mask_view; 226 227 Image 228 *mask_image; 229 230 MagickBooleanType 231 status; 232 233 ssize_t 234 y; 235 236 mask_image=CloneImage(image,image->columns,image->rows,MagickTrue, 237 exception); 238 if (mask_image == (Image *) NULL) 239 return((Image *) NULL); 240 if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse) 241 { 242 mask_image=DestroyImage(mask_image); 243 return((Image *) NULL); 244 } 245 mask_image->alpha_trait=UndefinedPixelTrait; 246 (void) SetImageColorspace(mask_image,GRAYColorspace,exception); 247 /* 248 Mask image. 249 */ 250 status=MagickTrue; 251 image_view=AcquireVirtualCacheView(image,exception); 252 mask_view=AcquireAuthenticCacheView(mask_image,exception); 253 for (y=0; y < (ssize_t) image->rows; y++) 254 { 255 register const Quantum 256 *magick_restrict p; 257 258 register Quantum 259 *magick_restrict q; 260 261 register ssize_t 262 x; 263 264 if (status == MagickFalse) 265 continue; 266 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 267 q=QueueCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1, 268 exception); 269 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 270 { 271 status=MagickFalse; 272 continue; 273 } 274 for (x=0; x < (ssize_t) image->columns; x++) 275 { 276 SetPixelChannel(mask_image,GrayPixelChannel,0,q); 277 SetPixelChannel(mask_image,GrayPixelChannel,GetPixelReadMask(image,p),q); 278 p+=GetPixelChannels(image); 279 q+=GetPixelChannels(mask_image); 280 } 281 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse) 282 status=MagickFalse; 283 } 284 mask_view=DestroyCacheView(mask_view); 285 image_view=DestroyCacheView(image_view); 286 if (status == MagickFalse) 287 mask_image=DestroyImage(mask_image); 288 return(mask_image); 289 } 290 291 static MagickBooleanType WriteMASKImage(const ImageInfo *image_info, 292 Image *image,ExceptionInfo *exception) 293 { 294 Image 295 *mask_image; 296 297 ImageInfo 298 *write_info; 299 300 MagickBooleanType 301 status; 302 303 mask_image=MaskImage(image,exception); 304 if (mask_image == (Image *) NULL) 305 return(MagickFalse); 306 (void) CopyMagickString(mask_image->filename,image->filename, 307 MagickPathExtent); 308 write_info=CloneImageInfo(image_info); 309 *write_info->magick='\0'; 310 (void) SetImageInfo(write_info,1,exception); 311 if ((*write_info->magick == '\0') || 312 (LocaleCompare(write_info->magick,"MASK") == 0)) 313 (void) FormatLocaleString(mask_image->filename,MagickPathExtent,"miff:%s", 314 write_info->filename); 315 status=WriteImage(write_info,mask_image,exception); 316 mask_image=DestroyImage(mask_image); 317 write_info=DestroyImageInfo(write_info); 318 return(status); 319 } 320