1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                 PPPP   L       AAA   SSSSS  M   M   AAA                     %
7%                 P   P  L      A   A  SS     MM MM  A   A                    %
8%                 PPPP   L      AAAAA   SSS   M M M  AAAAA                    %
9%                 P      L      A   A     SS  M   M  A   A                    %
10%                 P      LLLLL  A   A  SSSSS  M   M  A   A                    %
11%                                                                             %
12%                                                                             %
13%                          Read a Plasma Image.                               %
14%                                                                             %
15%                              Software Design                                %
16%                                   Cristy                                    %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2016 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%    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/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/channel.h"
47#include "MagickCore/constitute.h"
48#include "MagickCore/exception.h"
49#include "MagickCore/exception-private.h"
50#include "MagickCore/fx.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/random_.h"
60#include "MagickCore/random-private.h"
61#include "MagickCore/signature-private.h"
62#include "MagickCore/quantum-private.h"
63#include "MagickCore/static.h"
64#include "MagickCore/string_.h"
65#include "MagickCore/module.h"
66
67/*
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69%                                                                             %
70%                                                                             %
71%                                                                             %
72%   R e a d P L A S M A I m a g e                                             %
73%                                                                             %
74%                                                                             %
75%                                                                             %
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77%
78%  ReadPlasmaImage creates a plasma fractal image.  The image is
79%  initialized to the X server color as specified by the filename.
80%
81%  The format of the ReadPlasmaImage method is:
82%
83%      Image *ReadPlasmaImage(const ImageInfo *image_info,
84%        ExceptionInfo *exception)
85%
86%  A description of each parameter follows:
87%
88%    o image_info: the image info.
89%
90%    o exception: return any errors or warnings in this structure.
91%
92*/
93
94static inline void PlasmaPixel(Image *image,RandomInfo *random_info,double x,
95  double y,ExceptionInfo *exception)
96{
97  register Quantum
98    *q;
99
100  q=GetAuthenticPixels(image,(ssize_t) ceil(x-0.5),(ssize_t) ceil(y-0.5),1,1,
101    exception);
102  if (q == (Quantum *) NULL)
103    return;
104  SetPixelRed(image,ScaleShortToQuantum((unsigned short) (65535.0*
105    GetPseudoRandomValue(random_info)+0.5)),q);
106  SetPixelGreen(image,ScaleShortToQuantum((unsigned short) (65535.0*
107    GetPseudoRandomValue(random_info)+0.5)),q);
108  SetPixelBlue(image,ScaleShortToQuantum((unsigned short) (65535.0*
109    GetPseudoRandomValue(random_info)+0.5)),q);
110  (void) SyncAuthenticPixels(image,exception);
111}
112
113static Image *ReadPlasmaImage(const ImageInfo *image_info,
114  ExceptionInfo *exception)
115{
116  Image
117    *image;
118
119  ImageInfo
120    *read_info;
121
122  MagickBooleanType
123    status;
124
125  register ssize_t
126    x;
127
128  register Quantum
129    *q;
130
131  register size_t
132    i;
133
134  SegmentInfo
135    segment_info;
136
137  size_t
138    depth,
139    max_depth;
140
141  ssize_t
142    y;
143
144  /*
145    Recursively apply plasma to the image.
146  */
147  read_info=CloneImageInfo(image_info);
148  SetImageInfoBlob(read_info,(void *) NULL,0);
149  (void) FormatLocaleString(read_info->filename,MagickPathExtent,
150    "gradient:%s",image_info->filename);
151  image=ReadImage(read_info,exception);
152  read_info=DestroyImageInfo(read_info);
153  if (image == (Image *) NULL)
154    return((Image *) NULL);
155  (void) SetImageStorageClass(image,DirectClass,exception);
156  for (y=0; y < (ssize_t) image->rows; y++)
157  {
158    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
159    if (q == (Quantum *) NULL)
160      break;
161    for (x=0; x < (ssize_t) image->columns; x++)
162    {
163      SetPixelAlpha(image,QuantumRange/2,q);
164      q+=GetPixelChannels(image);
165    }
166    if (SyncAuthenticPixels(image,exception) == MagickFalse)
167      break;
168  }
169  segment_info.x1=0;
170  segment_info.y1=0;
171  segment_info.x2=(double) image->columns-1;
172  segment_info.y2=(double) image->rows-1;
173  if (LocaleCompare(image_info->filename,"fractal") == 0)
174    {
175      RandomInfo
176        *random_info;
177
178      /*
179        Seed pixels before recursion.
180      */
181      (void) SetImageColorspace(image,sRGBColorspace,exception);
182      random_info=AcquireRandomInfo();
183      PlasmaPixel(image,random_info,segment_info.x1,segment_info.y1,exception);
184      PlasmaPixel(image,random_info,segment_info.x1,(segment_info.y1+
185        segment_info.y2)/2,exception);
186      PlasmaPixel(image,random_info,segment_info.x1,segment_info.y2,exception);
187      PlasmaPixel(image,random_info,(segment_info.x1+segment_info.x2)/2,
188        segment_info.y1,exception);
189      PlasmaPixel(image,random_info,(segment_info.x1+segment_info.x2)/2,
190        (segment_info.y1+segment_info.y2)/2,exception);
191      PlasmaPixel(image,random_info,(segment_info.x1+segment_info.x2)/2,
192        segment_info.y2,exception);
193      PlasmaPixel(image,random_info,segment_info.x2,segment_info.y1,exception);
194      PlasmaPixel(image,random_info,segment_info.x2,(segment_info.y1+
195        segment_info.y2)/2,exception);
196      PlasmaPixel(image,random_info,segment_info.x2,segment_info.y2,exception);
197      random_info=DestroyRandomInfo(random_info);
198    }
199  i=(size_t) MagickMax(image->columns,image->rows)/2;
200  for (max_depth=0; i != 0; max_depth++)
201    i>>=1;
202  for (depth=1; ; depth++)
203  {
204    if (PlasmaImage(image,&segment_info,0,depth,exception) != MagickFalse)
205      break;
206    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) depth,
207      max_depth);
208    if (status == MagickFalse)
209      break;
210  }
211  return(GetFirstImageInList(image));
212}
213
214/*
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216%                                                                             %
217%                                                                             %
218%                                                                             %
219%   R e g i s t e r P L A S M A I m a g e                                     %
220%                                                                             %
221%                                                                             %
222%                                                                             %
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%
225%  RegisterPLASMAImage() adds attributes for the Plasma image format to
226%  the list of supported formats.  The attributes include the image format
227%  tag, a method to read and/or write the format, whether the format
228%  supports the saving of more than one frame to the same file or blob,
229%  whether the format supports native in-memory I/O, and a brief
230%  description of the format.
231%
232%  The format of the RegisterPLASMAImage method is:
233%
234%      size_t RegisterPLASMAImage(void)
235%
236*/
237ModuleExport size_t RegisterPLASMAImage(void)
238{
239  MagickInfo
240    *entry;
241
242  entry=AcquireMagickInfo("PLASMA","PLASMA","Plasma fractal image");
243  entry->decoder=(DecodeImageHandler *) ReadPlasmaImage;
244  entry->flags^=CoderAdjoinFlag;
245  entry->format_type=ImplicitFormatType;
246  (void) RegisterMagickInfo(entry);
247  entry=AcquireMagickInfo("PLASMA","FRACTAL","Plasma fractal image");
248  entry->decoder=(DecodeImageHandler *) ReadPlasmaImage;
249  entry->flags^=CoderAdjoinFlag;
250  entry->format_type=ImplicitFormatType;
251  (void) RegisterMagickInfo(entry);
252  return(MagickImageCoderSignature);
253}
254
255/*
256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257%                                                                             %
258%                                                                             %
259%                                                                             %
260%   U n r e g i s t e r P L A S M A I m a g e                                 %
261%                                                                             %
262%                                                                             %
263%                                                                             %
264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265%
266%  UnregisterPLASMAImage() removes format registrations made by the
267%  PLASMA module from the list of supported formats.
268%
269%  The format of the UnregisterPLASMAImage method is:
270%
271%      UnregisterPLASMAImage(void)
272%
273*/
274ModuleExport void UnregisterPLASMAImage(void)
275{
276  (void) UnregisterMagickInfo("FRACTAL");
277  (void) UnregisterMagickInfo("PLASMA");
278}
279