blob: b7c6a3e480127f9ece89ac61d9a5e5622aec9e77 [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% %
Cristyd8420112021-01-01 14:52:00 -050020% Copyright 1999-2021 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% %
Cristy83d74de2018-10-13 10:17:25 -040026% https://imagemagick.org/script/license.php %
cristy8fdeeb32013-03-31 21:15:31 +000027% %
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
Cristy2c85edd2018-06-10 16:59:14 -0400230 mask_image=CloneImage(image,0,0,MagickTrue,exception);
cristy8fdeeb32013-03-31 21:15:31 +0000231 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;
Cristybeb4c2b2017-12-26 19:43:17 -0500239 (void) SetImageColorspace(mask_image,GRAYColorspace,exception);
cristy8fdeeb32013-03-31 21:15:31 +0000240 /*
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 {
Cristyf2dc1dd2020-12-28 13:59:26 -0500248 const Quantum
dirk05d2ff72015-11-18 23:13:43 +0100249 *magick_restrict p;
cristy8fdeeb32013-03-31 21:15:31 +0000250
Cristyf2dc1dd2020-12-28 13:59:26 -0500251 Quantum
dirk05d2ff72015-11-18 23:13:43 +0100252 *magick_restrict q;
cristy8fdeeb32013-03-31 21:15:31 +0000253
Cristyf2dc1dd2020-12-28 13:59:26 -0500254 ssize_t
cristy8fdeeb32013-03-31 21:15:31 +0000255 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);
Cristydf5e8b12016-12-02 17:26:39 -0500270 SetPixelChannel(mask_image,GrayPixelChannel,GetPixelWriteMask(image,p),q);
cristy8fdeeb32013-03-31 21:15:31 +0000271 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
284static 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);
Cristye6fb02d2015-09-27 10:47:45 -0400299 (void) CopyMagickString(mask_image->filename,image->filename,
300 MagickPathExtent);
cristy8fdeeb32013-03-31 21:15:31 +0000301 write_info=CloneImageInfo(image_info);
Cristye6fb02d2015-09-27 10:47:45 -0400302 *write_info->magick='\0';
cristy8fdeeb32013-03-31 21:15:31 +0000303 (void) SetImageInfo(write_info,1,exception);
Cristy60f21f22016-07-04 09:03:59 -0400304 if ((*write_info->magick == '\0') ||
305 (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}