blob: f8bef4b9c70796c33c57e7bb2aef18ff5c1fd802 [file] [log] [blame]
cristy8fdeeb32013-03-31 21:15:31 +00001/*
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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy8fdeeb32013-03-31 21:15:31 +000017% July 1992 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy8fdeeb32013-03-31 21:15:31 +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 "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*/
64static 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*/
92static 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);
cristye1c94d92015-06-28 12:16:33 +0000105 assert(image_info->signature == MagickCoreSignature);
cristy8fdeeb32013-03-31 21:15:31 +0000106 if (image_info->debug != MagickFalse)
107 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
108 image_info->filename);
109 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000110 assert(exception->signature == MagickCoreSignature);
cristy8fdeeb32013-03-31 21:15:31 +0000111 read_info=CloneImageInfo(image_info);
112 SetImageInfoBlob(read_info,(void *) NULL,0);
cristy151b66d2015-04-15 10:50:31 +0000113 (void) CopyMagickString(read_info->magick,"MIFF",MagickPathExtent);
cristy8fdeeb32013-03-31 21:15:31 +0000114 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*/
151ModuleExport size_t RegisterMASKImage(void)
152{
153 MagickInfo
154 *entry;
155
dirk06b627a2015-04-06 18:59:17 +0000156 entry=AcquireMagickInfo("MASK","MASK","Image Clip Mask");
cristy8fdeeb32013-03-31 21:15:31 +0000157 entry->decoder=(DecodeImageHandler *) ReadMASKImage;
158 entry->encoder=(EncodeImageHandler *) WriteMASKImage;
cristy8fdeeb32013-03-31 21:15:31 +0000159 (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*/
182ModuleExport 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
215static 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,image->columns,image->rows,MagickTrue,
231 exception);
232 if (mask_image == (Image *) NULL)
233 return((Image *) NULL);
234 if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
235 {
236 mask_image=DestroyImage(mask_image);
237 return((Image *) NULL);
238 }
239 mask_image->alpha_trait=UndefinedPixelTrait;
240 (void) SetImageColorspace(mask_image,GRAYColorspace,exception);
241 /*
242 Mask image.
243 */
244 status=MagickTrue;
245 image_view=AcquireVirtualCacheView(image,exception);
246 mask_view=AcquireAuthenticCacheView(mask_image,exception);
247 for (y=0; y < (ssize_t) image->rows; y++)
248 {
249 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100250 *magick_restrict p;
cristy8fdeeb32013-03-31 21:15:31 +0000251
252 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100253 *magick_restrict q;
cristy8fdeeb32013-03-31 21:15:31 +0000254
255 register ssize_t
256 x;
257
258 if (status == MagickFalse)
259 continue;
260 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
261 q=QueueCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
262 exception);
263 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
264 {
265 status=MagickFalse;
266 continue;
267 }
268 for (x=0; x < (ssize_t) image->columns; x++)
269 {
270 SetPixelChannel(mask_image,GrayPixelChannel,0,q);
cristy883fde12013-04-08 00:50:13 +0000271 SetPixelChannel(mask_image,GrayPixelChannel,GetPixelReadMask(image,p),q);
cristy8fdeeb32013-03-31 21:15:31 +0000272 p+=GetPixelChannels(image);
273 q+=GetPixelChannels(mask_image);
274 }
275 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
276 status=MagickFalse;
277 }
278 mask_view=DestroyCacheView(mask_view);
279 image_view=DestroyCacheView(image_view);
280 if (status == MagickFalse)
281 mask_image=DestroyImage(mask_image);
282 return(mask_image);
283}
284
285static MagickBooleanType WriteMASKImage(const ImageInfo *image_info,
286 Image *image,ExceptionInfo *exception)
287{
288 Image
289 *mask_image;
290
291 ImageInfo
292 *write_info;
293
294 MagickBooleanType
295 status;
296
297 mask_image=MaskImage(image,exception);
298 if (mask_image == (Image *) NULL)
299 return(MagickFalse);
Cristye6fb02d2015-09-27 10:47:45 -0400300 (void) CopyMagickString(mask_image->filename,image->filename,
301 MagickPathExtent);
cristy8fdeeb32013-03-31 21:15:31 +0000302 write_info=CloneImageInfo(image_info);
Cristye6fb02d2015-09-27 10:47:45 -0400303 *write_info->magick='\0';
cristy8fdeeb32013-03-31 21:15:31 +0000304 (void) SetImageInfo(write_info,1,exception);
305 if (LocaleCompare(write_info->magick,"MASK") == 0)
cristy151b66d2015-04-15 10:50:31 +0000306 (void) FormatLocaleString(mask_image->filename,MagickPathExtent,"miff:%s",
cristy8fdeeb32013-03-31 21:15:31 +0000307 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}