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