1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % K K EEEEE RRRR N N EEEEE L %
7 % K K E R R NN N E L %
8 % KKK EEE RRRR N N N EEE L %
9 % K K E R R N NN E L %
10 % K K EEEEE R R N N EEEEE LLLLL %
11 % %
12 % %
13 % Write the Morphology Kernel Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % October 2020 %
18 % %
19 % %
20 % Copyright 1999-2021 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 % Adapted from http://im.snibgo.com/customim.htm#img2knl.c.
37 %
38 */
39
40 /*
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/colorspace.h"
48 #include "MagickCore/colorspace-private.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 /*
65 Forward declarations.
66 */
67 static MagickBooleanType
68 WriteKERNELImage(const ImageInfo *,Image *,ExceptionInfo *);
69
70 /*
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 % %
73 % %
74 % %
75 % R e g i s t e r K E R N E L I m a g e %
76 % %
77 % %
78 % %
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %
81 % RegisterKERNELImage() adds attributes for the KERNEL image format to the
82 % list of supported formats. The attributes include the image format tag, a
83 % method to read and/or write the format, whether the format supports the
84 % saving of more than one frame to the same file or blob, whether the format
85 % supports native in-memory I/O, and a brief description of the format.
86 %
87 % The format of the RegisterKERNELImage method is:
88 %
89 % size_t RegisterKERNELImage(void)
90 %
91 */
RegisterKERNELImage(void)92 ModuleExport size_t RegisterKERNELImage(void)
93 {
94 MagickInfo
95 *entry;
96
97 entry=AcquireMagickInfo("KERNEL","KERNEL","Morphology Kernel");
98 entry->encoder=(EncodeImageHandler *) WriteKERNELImage;
99 entry->flags^=CoderAdjoinFlag;
100 (void) RegisterMagickInfo(entry);
101 return(MagickImageCoderSignature);
102 }
103
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 % %
107 % %
108 % %
109 % U n r e g i s t e r K E R N E L I m a g e %
110 % %
111 % %
112 % %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 % UnregisterKERNELImage() removes format registrations made by the
116 % KERNEL module from the list of supported formats.
117 %
118 % The format of the UnregisterKERNELImage method is:
119 %
120 % UnregisterKERNELImage(void)
121 %
122 */
UnregisterKERNELImage(void)123 ModuleExport void UnregisterKERNELImage(void)
124 {
125 (void) UnregisterMagickInfo("KERNEL");
126 }
127
128 /*
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 % %
131 % %
132 % %
133 % W r i t e K E R N E L I m a g e %
134 % %
135 % %
136 % %
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 %
139 % WriteKERNELImage() writes an image to a file in KERNEL image format.
140 %
141 % The format of the WriteKERNELImage method is:
142 %
143 % MagickBooleanType WriteKERNELImage(const ImageInfo *image_info,
144 % Image *image,ExceptionInfo *exception)
145 %
146 % A description of each parameter follows.
147 %
148 % o image_info: the image info.
149 %
150 % o image: The image.
151 %
152 % o exception: return any errors or warnings in this structure.
153 %
154 */
WriteKERNELImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)155 static MagickBooleanType WriteKERNELImage(const ImageInfo *image_info,
156 Image *image,ExceptionInfo *exception)
157 {
158 char
159 buffer[MagickPathExtent];
160
161 MagickBooleanType
162 status;
163
164 ssize_t
165 y;
166
167 /*
168 Open output image file.
169 */
170 assert(image_info != (const ImageInfo *) NULL);
171 assert(image_info->signature == MagickCoreSignature);
172 assert(image != (Image *) NULL);
173 assert(image->signature == MagickCoreSignature);
174 if (image->debug != MagickFalse)
175 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
176 assert(exception != (ExceptionInfo *) NULL);
177 assert(exception->signature == MagickCoreSignature);
178 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
179 if (status == MagickFalse)
180 return(status);
181 /*
182 Write KERNEL header.
183 */
184 (void) TransformImageColorspace(image,sRGBColorspace,exception);
185 (void) FormatLocaleString(buffer,MagickPathExtent,"%gx%g:",(double)
186 image->columns,(double) image->rows);
187 (void) WriteBlobString(image,buffer);
188 /*
189 Convert MIFF to KERNEL raster pixels.
190 */
191 for (y=0; y < (ssize_t) image->rows; y++)
192 {
193 const Quantum
194 *magick_restrict p;
195
196 ssize_t
197 x;
198
199 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
200 if (p == (const Quantum *) NULL)
201 break;
202 for (x=0; x < (ssize_t) image->columns; x++)
203 {
204 if ((x != 0) || (y != 0))
205 (void) WriteBlobString(image,",");
206 if ((image->alpha_trait == BlendPixelTrait) &&
207 (GetPixelAlpha(image,p) < OpaqueAlpha/2))
208 (void) WriteBlobString(image,"-");
209 else
210 {
211 (void) FormatLocaleString(buffer,MagickPathExtent,"%.*g",
212 GetMagickPrecision(),QuantumScale*GetPixelIntensity(image,p));
213 (void) WriteBlobString(image,buffer);
214 }
215 p+=GetPixelChannels(image);
216 }
217 if (image->previous == (Image *) NULL)
218 {
219 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
220 image->rows);
221 if (status == MagickFalse)
222 break;
223 }
224 }
225 (void) WriteBlobString(image,"\n");
226 (void) CloseBlob(image);
227 return(MagickTrue);
228 }
229