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