1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % SSSSS CCCC TTTTT % 7 % SS C T % 8 % SSS C T % 9 % SS C T % 10 % SSSSS CCCC T % 11 % % 12 % % 13 % Read Scitex HandShake Image Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2019 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 % 37 */ 38 39 /* 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/exception.h" 48 #include "MagickCore/exception-private.h" 49 #include "MagickCore/image.h" 50 #include "MagickCore/image-private.h" 51 #include "MagickCore/list.h" 52 #include "MagickCore/magick.h" 53 #include "MagickCore/memory_.h" 54 #include "MagickCore/module.h" 55 #include "MagickCore/monitor.h" 56 #include "MagickCore/monitor-private.h" 57 #include "MagickCore/pixel-accessor.h" 58 #include "MagickCore/quantum-private.h" 59 #include "MagickCore/static.h" 60 #include "MagickCore/string_.h" 61 #include "MagickCore/string-private.h" 62 63 /* 65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 66 % % 67 % % 68 % % 69 % I s S C T % 70 % % 71 % % 72 % % 73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 % 75 % IsSCT() returns MagickTrue if the image format type, identified by the 76 % magick string, is SCT. 77 % 78 % The format of the IsSCT method is: 79 % 80 % MagickBooleanType IsSCT(const unsigned char *magick,const size_t length) 81 % 82 % A description of each parameter follows: 83 % 84 % o magick: compare image format pattern against these bytes. 85 % 86 % o length: Specifies the length of the magick string. 87 % 88 */ 89 static MagickBooleanType IsSCT(const unsigned char *magick,const size_t length) 90 { 91 if (length < 2) 92 return(MagickFalse); 93 if (LocaleNCompare((const char *) magick,"CT",2) == 0) 94 return(MagickTrue); 95 return(MagickFalse); 96 } 97 98 /* 100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 101 % % 102 % % 103 % % 104 % R e a d S C T I m a g e % 105 % % 106 % % 107 % % 108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 109 % 110 % ReadSCTImage() reads a Scitex image file and returns it. It allocates 111 % the memory necessary for the new Image structure and returns a pointer to 112 % the new image. 113 % 114 % The format of the ReadSCTImage method is: 115 % 116 % Image *ReadSCTImage(const ImageInfo *image_info,ExceptionInfo *exception) 117 % 118 % A description of each parameter follows: 119 % 120 % o image_info: the image info. 121 % 122 % o exception: return any errors or warnings in this structure. 123 % 124 */ 125 static Image *ReadSCTImage(const ImageInfo *image_info,ExceptionInfo *exception) 126 { 127 char 128 magick[2]; 129 130 Image 131 *image; 132 133 MagickBooleanType 134 status; 135 136 double 137 height, 138 width; 139 140 int 141 c; 142 143 Quantum 144 pixel; 145 146 register ssize_t 147 i, 148 x; 149 150 register Quantum 151 *q; 152 153 ssize_t 154 count, 155 y; 156 157 unsigned char 158 buffer[768]; 159 160 size_t 161 separations, 162 separations_mask, 163 units; 164 165 /* 166 Open image file. 167 */ 168 assert(image_info != (const ImageInfo *) NULL); 169 assert(image_info->signature == MagickCoreSignature); 170 if (image_info->debug != MagickFalse) 171 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 172 image_info->filename); 173 assert(exception != (ExceptionInfo *) NULL); 174 assert(exception->signature == MagickCoreSignature); 175 image=AcquireImage(image_info,exception); 176 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 177 if (status == MagickFalse) 178 { 179 image=DestroyImageList(image); 180 return((Image *) NULL); 181 } 182 /* 183 Read control block. 184 */ 185 memset(magick,0,sizeof(magick)); 186 memset(buffer,0,sizeof(buffer)); 187 count=ReadBlob(image,80,buffer); 188 (void) count; 189 count=ReadBlob(image,2,(unsigned char *) magick); 190 if ((LocaleNCompare((char *) magick,"CT",2) != 0) && 191 (LocaleNCompare((char *) magick,"LW",2) != 0) && 192 (LocaleNCompare((char *) magick,"BM",2) != 0) && 193 (LocaleNCompare((char *) magick,"PG",2) != 0) && 194 (LocaleNCompare((char *) magick,"TX",2) != 0)) 195 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 196 if ((LocaleNCompare((char *) magick,"LW",2) == 0) || 197 (LocaleNCompare((char *) magick,"BM",2) == 0) || 198 (LocaleNCompare((char *) magick,"PG",2) == 0) || 199 (LocaleNCompare((char *) magick,"TX",2) == 0)) 200 ThrowReaderException(CoderError,"OnlyContinuousTonePictureSupported"); 201 count=ReadBlob(image,174,buffer); 202 count=ReadBlob(image,768,buffer); 203 /* 204 Read paramter block. 205 */ 206 units=1UL*ReadBlobByte(image); 207 if (units == 0) 208 image->units=PixelsPerCentimeterResolution; 209 separations=1UL*ReadBlobByte(image); 210 separations_mask=ReadBlobMSBShort(image); 211 count=ReadBlob(image,14,buffer); 212 buffer[14]='\0'; 213 height=StringToDouble((char *) buffer,(char **) NULL); 214 count=ReadBlob(image,14,buffer); 215 width=StringToDouble((char *) buffer,(char **) NULL); 216 count=ReadBlob(image,12,buffer); 217 buffer[12]='\0'; 218 image->rows=StringToUnsignedLong((char *) buffer); 219 count=ReadBlob(image,12,buffer); 220 image->columns=StringToUnsignedLong((char *) buffer); 221 count=ReadBlob(image,200,buffer); 222 count=ReadBlob(image,768,buffer); 223 if (separations_mask == 0x0f) 224 SetImageColorspace(image,CMYKColorspace,exception); 225 if ((image->columns < 1) || (image->rows < 1) || 226 (width < MagickEpsilon) || (height < MagickEpsilon)) 227 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 228 image->resolution.x=1.0*image->columns/width; 229 image->resolution.y=1.0*image->rows/height; 230 if (image_info->ping != MagickFalse) 231 { 232 (void) CloseBlob(image); 233 return(GetFirstImageInList(image)); 234 } 235 status=SetImageExtent(image,image->columns,image->rows,exception); 236 if (status == MagickFalse) 237 return(DestroyImageList(image)); 238 /* 239 Convert SCT raster image to pixel packets. 240 */ 241 c=0; 242 for (y=0; y < (ssize_t) image->rows; y++) 243 { 244 for (i=0; i < (ssize_t) separations; i++) 245 { 246 q=GetAuthenticPixels(image,0,y,image->columns,1,exception); 247 if (q == (Quantum *) NULL) 248 break; 249 for (x=0; x < (ssize_t) image->columns; x++) 250 { 251 c=ReadBlobByte(image); 252 if (c == EOF) 253 break; 254 pixel=(Quantum) ScaleCharToQuantum((unsigned char) c); 255 if (image->colorspace == CMYKColorspace) 256 pixel=(Quantum) (QuantumRange-pixel); 257 switch (i) 258 { 259 case 0: 260 { 261 SetPixelRed(image,pixel,q); 262 SetPixelGreen(image,pixel,q); 263 SetPixelBlue(image,pixel,q); 264 break; 265 } 266 case 1: 267 { 268 SetPixelGreen(image,pixel,q); 269 break; 270 } 271 case 2: 272 { 273 SetPixelBlue(image,pixel,q); 274 break; 275 } 276 case 3: 277 { 278 if (image->colorspace == CMYKColorspace) 279 SetPixelBlack(image,pixel,q); 280 break; 281 } 282 } 283 q+=GetPixelChannels(image); 284 } 285 if (x < (ssize_t) image->columns) 286 break; 287 if (SyncAuthenticPixels(image,exception) == MagickFalse) 288 break; 289 if ((image->columns % 2) != 0) 290 (void) ReadBlobByte(image); /* pad */ 291 } 292 if (i < (ssize_t) separations) 293 break; 294 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 295 image->rows); 296 if (status == MagickFalse) 297 break; 298 } 299 if (EOFBlob(image) != MagickFalse) 300 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 301 image->filename); 302 (void) CloseBlob(image); 303 return(GetFirstImageInList(image)); 304 } 305 306 /* 308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 309 % % 310 % % 311 % % 312 % R e g i s t e r S C T I m a g e % 313 % % 314 % % 315 % % 316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 317 % 318 % RegisterSCTImage() adds attributes for the SCT image format to 319 % the list of supported formats. The attributes include the image format 320 % tag, a method to read and/or write the format, whether the format 321 % supports the saving of more than one frame to the same file or blob, 322 % whether the format supports native in-memory I/O, and a brief 323 % description of the format. 324 % 325 % The format of the RegisterSCTImage method is: 326 % 327 % size_t RegisterSCTImage(void) 328 % 329 */ 330 ModuleExport size_t RegisterSCTImage(void) 331 { 332 MagickInfo 333 *entry; 334 335 entry=AcquireMagickInfo("SCT","SCT","Scitex HandShake"); 336 entry->decoder=(DecodeImageHandler *) ReadSCTImage; 337 entry->magick=(IsImageFormatHandler *) IsSCT; 338 entry->flags^=CoderAdjoinFlag; 339 (void) RegisterMagickInfo(entry); 340 return(MagickImageCoderSignature); 341 } 342 343 /* 345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 346 % % 347 % % 348 % % 349 % U n r e g i s t e r S C T I m a g e % 350 % % 351 % % 352 % % 353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 354 % 355 % UnregisterSCTImage() removes format registrations made by the 356 % SCT module from the list of supported formats. 357 % 358 % The format of the UnregisterSCTImage method is: 359 % 360 % UnregisterSCTImage(void) 361 % 362 */ 363 ModuleExport void UnregisterSCTImage(void) 364 { 365 (void) UnregisterMagickInfo("SCT"); 366 } 367