1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % L AAA BBBB EEEEE L % 7 % L A A B B E L % 8 % L AAAAA BBBB EEE L % 9 % L A A B B E L % 10 % LLLLL A A BBBB EEEEE LLLLL % 11 % % 12 % % 13 % Read ASCII String As An 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 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/annotate.h" 45 #include "MagickCore/artifact.h" 46 #include "MagickCore/blob.h" 47 #include "MagickCore/blob-private.h" 48 #include "MagickCore/draw.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/property.h" 57 #include "MagickCore/quantum-private.h" 58 #include "MagickCore/static.h" 59 #include "MagickCore/string_.h" 60 #include "MagickCore/module.h" 61 #include "MagickCore/utility.h" 62 63 /* 65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 66 % % 67 % % 68 % % 69 % R e a d L A B E L I m a g e % 70 % % 71 % % 72 % % 73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 % 75 % ReadLABELImage() reads a LABEL image file and returns it. It 76 % allocates the memory necessary for the new Image structure and returns a 77 % pointer to the new image. 78 % 79 % The format of the ReadLABELImage method is: 80 % 81 % Image *ReadLABELImage(const ImageInfo *image_info, 82 % ExceptionInfo *exception) 83 % 84 % A description of each parameter follows: 85 % 86 % o image_info: the image info. 87 % 88 % o exception: return any errors or warnings in this structure. 89 % 90 */ 91 static Image *ReadLABELImage(const ImageInfo *image_info, 92 ExceptionInfo *exception) 93 { 94 char 95 geometry[MagickPathExtent], 96 *property; 97 98 const char 99 *label; 100 101 DrawInfo 102 *draw_info; 103 104 Image 105 *image; 106 107 MagickBooleanType 108 status; 109 110 TypeMetric 111 metrics; 112 113 size_t 114 height, 115 width; 116 117 /* 118 Initialize Image structure. 119 */ 120 assert(image_info != (const ImageInfo *) NULL); 121 assert(image_info->signature == MagickCoreSignature); 122 if (image_info->debug != MagickFalse) 123 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 124 image_info->filename); 125 assert(exception != (ExceptionInfo *) NULL); 126 assert(exception->signature == MagickCoreSignature); 127 image=AcquireImage(image_info,exception); 128 (void) ResetImagePage(image,"0x0+0+0"); 129 property=InterpretImageProperties((ImageInfo *) image_info,image, 130 image_info->filename,exception); 131 (void) SetImageProperty(image,"label",property,exception); 132 property=DestroyString(property); 133 label=GetImageProperty(image,"label",exception); 134 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); 135 draw_info->text=ConstantString(label); 136 metrics.width=0; 137 metrics.ascent=0.0; 138 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); 139 if ((image->columns == 0) && (image->rows == 0)) 140 { 141 image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); 142 image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); 143 } 144 else 145 if ((strlen(label) > 0) && 146 (((image->columns == 0) || (image->rows == 0)) || 147 (fabs(image_info->pointsize) < MagickEpsilon))) 148 { 149 double 150 high, 151 low; 152 153 /* 154 Auto fit text into bounding box. 155 */ 156 for ( ; ; draw_info->pointsize*=2.0) 157 { 158 (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", 159 -metrics.bounds.x1,metrics.ascent); 160 if (draw_info->gravity == UndefinedGravity) 161 (void) CloneString(&draw_info->geometry,geometry); 162 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); 163 width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); 164 height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); 165 if ((image->columns != 0) && (image->rows != 0)) 166 { 167 if ((width >= image->columns) && (height >= image->rows)) 168 break; 169 } 170 else 171 if (((image->columns != 0) && (width >= image->columns)) || 172 ((image->rows != 0) && (height >= image->rows))) 173 break; 174 } 175 high=draw_info->pointsize; 176 for (low=1.0; (high-low) > 0.5; ) 177 { 178 draw_info->pointsize=(low+high)/2.0; 179 (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", 180 -metrics.bounds.x1,metrics.ascent); 181 if (draw_info->gravity == UndefinedGravity) 182 (void) CloneString(&draw_info->geometry,geometry); 183 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); 184 width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); 185 height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); 186 if ((image->columns != 0) && (image->rows != 0)) 187 { 188 if ((width < image->columns) && (height < image->rows)) 189 low=draw_info->pointsize+0.5; 190 else 191 high=draw_info->pointsize-0.5; 192 } 193 else 194 if (((image->columns != 0) && (width < image->columns)) || 195 ((image->rows != 0) && (height < image->rows))) 196 low=draw_info->pointsize+0.5; 197 else 198 high=draw_info->pointsize-0.5; 199 } 200 draw_info->pointsize=(low+high)/2.0-0.5; 201 } 202 status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); 203 if (status == MagickFalse) 204 { 205 draw_info=DestroyDrawInfo(draw_info); 206 image=DestroyImageList(image); 207 return((Image *) NULL); 208 } 209 if (image->columns == 0) 210 image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); 211 if (image->columns == 0) 212 image->columns=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+ 213 0.5); 214 if (image->rows == 0) 215 image->rows=(size_t) floor(metrics.ascent-metrics.descent+ 216 draw_info->stroke_width+0.5); 217 if (image->rows == 0) 218 image->rows=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+ 219 0.5); 220 status=SetImageExtent(image,image->columns,image->rows,exception); 221 if (status == MagickFalse) 222 { 223 draw_info=DestroyDrawInfo(draw_info); 224 return(DestroyImageList(image)); 225 } 226 if (SetImageBackgroundColor(image,exception) == MagickFalse) 227 { 228 draw_info=DestroyDrawInfo(draw_info); 229 image=DestroyImageList(image); 230 return((Image *) NULL); 231 } 232 /* 233 Draw label. 234 */ 235 (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", 236 draw_info->direction == RightToLeftDirection ? image->columns- 237 metrics.bounds.x2 : 0.0,draw_info->gravity == UndefinedGravity ? 238 metrics.ascent : 0.0); 239 draw_info->geometry=AcquireString(geometry); 240 status=AnnotateImage(image,draw_info,exception); 241 if (image_info->pointsize == 0.0) 242 { 243 char 244 pointsize[MagickPathExtent]; 245 246 (void) FormatLocaleString(pointsize,MagickPathExtent,"%.20g", 247 draw_info->pointsize); 248 (void) SetImageProperty(image,"label:pointsize",pointsize,exception); 249 } 250 draw_info=DestroyDrawInfo(draw_info); 251 if (status == MagickFalse) 252 { 253 image=DestroyImageList(image); 254 return((Image *) NULL); 255 } 256 return(GetFirstImageInList(image)); 257 } 258 259 /* 261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 262 % % 263 % % 264 % % 265 % R e g i s t e r L A B E L I m a g e % 266 % % 267 % % 268 % % 269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 270 % 271 % RegisterLABELImage() adds properties for the LABEL image format to 272 % the list of supported formats. The properties include the image format 273 % tag, a method to read and/or write the format, whether the format 274 % supports the saving of more than one frame to the same file or blob, 275 % whether the format supports native in-memory I/O, and a brief 276 % description of the format. 277 % 278 % The format of the RegisterLABELImage method is: 279 % 280 % size_t RegisterLABELImage(void) 281 % 282 */ 283 ModuleExport size_t RegisterLABELImage(void) 284 { 285 MagickInfo 286 *entry; 287 288 entry=AcquireMagickInfo("LABEL","LABEL","Image label"); 289 entry->decoder=(DecodeImageHandler *) ReadLABELImage; 290 entry->flags^=CoderAdjoinFlag; 291 entry->format_type=ImplicitFormatType; 292 (void) RegisterMagickInfo(entry); 293 return(MagickImageCoderSignature); 294 } 295 296 /* 298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 299 % % 300 % % 301 % % 302 % U n r e g i s t e r L A B E L I m a g e % 303 % % 304 % % 305 % % 306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 307 % 308 % UnregisterLABELImage() removes format registrations made by the 309 % LABEL module from the list of supported formats. 310 % 311 % The format of the UnregisterLABELImage method is: 312 % 313 % UnregisterLABELImage(void) 314 % 315 */ 316 ModuleExport void UnregisterLABELImage(void) 317 { 318 (void) UnregisterMagickInfo("LABEL"); 319 } 320