1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % CCC U U TTTTT % 6 % C U U T % 7 % C U U T % 8 % C U U T % 9 % CCC UUU T % 10 % % 11 % % 12 % Read DR Halo Image Format % 13 % % 14 % Software Design % 15 % Jaroslav Fojtik % 16 % June 2000 % 17 % % 18 % % 19 % Permission is hereby granted, free of charge, to any person obtaining a % 20 % copy of this software and associated documentation files ("ImageMagick"), % 21 % to deal in ImageMagick without restriction, including without limitation % 22 % the rights to use, copy, modify, merge, publish, distribute, sublicense, % 23 % and/or sell copies of ImageMagick, and to permit persons to whom the % 24 % ImageMagick is furnished to do so, subject to the following conditions: % 25 % % 26 % The above copyright notice and this permission notice shall be included in % 27 % all copies or substantial portions of ImageMagick. % 28 % % 29 % The software is provided "as is", without warranty of any kind, express or % 30 % implied, including but not limited to the warranties of merchantability, % 31 % fitness for a particular purpose and noninfringement. In no event shall % 32 % ImageMagick Studio be liable for any claim, damages or other liability, % 33 % whether in an action of contract, tort or otherwise, arising from, out of % 34 % or in connection with ImageMagick or the use or other dealings in % 35 % ImageMagick. % 36 % % 37 % Except as contained in this notice, the name of the ImageMagick Studio % 38 % shall not be used in advertising or otherwise to promote the sale, use or % 39 % other dealings in ImageMagick without prior written authorization from the % 40 % ImageMagick Studio. % 41 % % 42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 % 44 % 45 */ 46 47 /* 49 Include declarations. 50 */ 51 #include "MagickCore/studio.h" 52 #include "MagickCore/attribute.h" 53 #include "MagickCore/blob.h" 54 #include "MagickCore/blob-private.h" 55 #include "MagickCore/cache.h" 56 #include "MagickCore/color.h" 57 #include "MagickCore/color-private.h" 58 #include "MagickCore/colormap.h" 59 #include "MagickCore/colormap-private.h" 60 #include "MagickCore/exception.h" 61 #include "MagickCore/exception-private.h" 62 #include "MagickCore/image.h" 63 #include "MagickCore/image-private.h" 64 #include "MagickCore/list.h" 65 #include "MagickCore/magick.h" 66 #include "MagickCore/memory_.h" 67 #include "MagickCore/pixel-accessor.h" 68 #include "MagickCore/quantum-private.h" 69 #include "MagickCore/static.h" 70 #include "MagickCore/string_.h" 71 #include "MagickCore/module.h" 72 #include "MagickCore/utility.h" 73 #include "MagickCore/utility-private.h" 74 75 typedef struct 77 { 78 unsigned Width; 79 unsigned Height; 80 unsigned Reserved; 81 } CUTHeader; 82 83 typedef struct 84 { 85 char FileId[2]; 86 unsigned Version; 87 unsigned Size; 88 char FileType; 89 char SubType; 90 unsigned BoardID; 91 unsigned GraphicsMode; 92 unsigned MaxIndex; 93 unsigned MaxRed; 94 unsigned MaxGreen; 95 unsigned MaxBlue; 96 char PaletteId[20]; 97 } CUTPalHeader; 98 99 100 static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p, 102 ssize_t y,ExceptionInfo *exception) 103 { 104 int 105 bit; 106 107 Quantum 108 index; 109 110 register Quantum 111 *q; 112 113 ssize_t 114 x; 115 116 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 117 if (q == (Quantum *) NULL) 118 return(MagickFalse); 119 switch (bpp) 120 { 121 case 1: /* Convert bitmap scanline. */ 122 { 123 for (x=0; x < ((ssize_t) image->columns-7); x+=8) 124 { 125 for (bit=0; bit < 8; bit++) 126 { 127 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00); 128 SetPixelIndex(image,index,q); 129 if (index < image->colors) 130 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 131 q+=GetPixelChannels(image); 132 } 133 p++; 134 } 135 if ((image->columns % 8) != 0) 136 { 137 for (bit=0; bit < (ssize_t) (image->columns % 8); bit++) 138 { 139 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00); 140 SetPixelIndex(image,index,q); 141 if (index < image->colors) 142 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 143 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 144 q+=GetPixelChannels(image); 145 } 146 p++; 147 } 148 break; 149 } 150 case 2: /* Convert PseudoColor scanline. */ 151 { 152 for (x=0; x < ((ssize_t) image->columns-3); x+=4) 153 { 154 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception); 155 SetPixelIndex(image,index,q); 156 if (index < image->colors) 157 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 158 q+=GetPixelChannels(image); 159 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception); 160 SetPixelIndex(image,index,q); 161 if (index < image->colors) 162 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 163 q+=GetPixelChannels(image); 164 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception); 165 SetPixelIndex(image,index,q); 166 if (index < image->colors) 167 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 168 q+=GetPixelChannels(image); 169 index=ConstrainColormapIndex(image,(*p) & 0x3,exception); 170 SetPixelIndex(image,index,q); 171 if (index < image->colors) 172 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 173 q+=GetPixelChannels(image); 174 p++; 175 } 176 if ((image->columns % 4) != 0) 177 { 178 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception); 179 SetPixelIndex(image,index,q); 180 if (index < image->colors) 181 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 182 q+=GetPixelChannels(image); 183 if ((image->columns % 4) > 1) 184 { 185 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception); 186 SetPixelIndex(image,index,q); 187 if (index < image->colors) 188 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 189 q+=GetPixelChannels(image); 190 if ((image->columns % 4) > 2) 191 { 192 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3, 193 exception); 194 SetPixelIndex(image,index,q); 195 if (index < image->colors) 196 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) 197 index,q); 198 q+=GetPixelChannels(image); 199 } 200 } 201 p++; 202 } 203 break; 204 } 205 206 case 4: /* Convert PseudoColor scanline. */ 207 { 208 for (x=0; x < ((ssize_t) image->columns-1); x+=2) 209 { 210 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception); 211 SetPixelIndex(image,index,q); 212 if (index < image->colors) 213 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 214 q+=GetPixelChannels(image); 215 index=ConstrainColormapIndex(image,(*p) & 0x0f,exception); 216 SetPixelIndex(image,index,q); 217 if (index < image->colors) 218 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 219 p++; 220 q+=GetPixelChannels(image); 221 } 222 if ((image->columns % 2) != 0) 223 { 224 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception); 225 SetPixelIndex(image,index,q); 226 if (index < image->colors) 227 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 228 p++; 229 q+=GetPixelChannels(image); 230 } 231 break; 232 } 233 case 8: /* Convert PseudoColor scanline. */ 234 { 235 for (x=0; x < (ssize_t) image->columns; x++) 236 { 237 index=ConstrainColormapIndex(image,*p,exception); 238 SetPixelIndex(image,index,q); 239 if (index < image->colors) 240 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 241 p++; 242 q+=GetPixelChannels(image); 243 } 244 } 245 break; 246 247 case 24: /* Convert DirectColor scanline. */ 248 for (x=0; x < (ssize_t) image->columns; x++) 249 { 250 SetPixelRed(image,ScaleCharToQuantum(*p++),q); 251 SetPixelGreen(image,ScaleCharToQuantum(*p++),q); 252 SetPixelBlue(image,ScaleCharToQuantum(*p++),q); 253 q+=GetPixelChannels(image); 254 } 255 break; 256 } 257 if (!SyncAuthenticPixels(image,exception)) 258 return(MagickFalse); 259 return(MagickTrue); 260 } 261 262 /* 263 Compute the number of colors in Grayed R[i]=G[i]=B[i] image 264 */ 265 static int GetCutColors(Image *image,ExceptionInfo *exception) 266 { 267 Quantum 268 intensity, 269 scale_intensity; 270 271 register Quantum 272 *q; 273 274 ssize_t 275 x, 276 y; 277 278 intensity=0; 279 scale_intensity=ScaleCharToQuantum(16); 280 for (y=0; y < (ssize_t) image->rows; y++) 281 { 282 q=GetAuthenticPixels(image,0,y,image->columns,1,exception); 283 if (q == (Quantum *) NULL) 284 break; 285 for (x=0; x < (ssize_t) image->columns; x++) 286 { 287 if (intensity < GetPixelRed(image,q)) 288 intensity=GetPixelRed(image,q); 289 if (intensity >= scale_intensity) 290 return(255); 291 q+=GetPixelChannels(image); 292 } 293 } 294 if (intensity < ScaleCharToQuantum(2)) 295 return(2); 296 if (intensity < ScaleCharToQuantum(16)) 297 return(16); 298 return((int) intensity); 299 } 300 301 /* 303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 304 % % 305 % % 306 % % 307 % R e a d C U T I m a g e % 308 % % 309 % % 310 % % 311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 312 % 313 % ReadCUTImage() reads an CUT X image file and returns it. It 314 % allocates the memory necessary for the new Image structure and returns a 315 % pointer to the new image. 316 % 317 % The format of the ReadCUTImage method is: 318 % 319 % Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) 320 % 321 % A description of each parameter follows: 322 % 323 % o image_info: the image info. 324 % 325 % o exception: return any errors or warnings in this structure. 326 % 327 */ 328 static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) 329 { 330 #define ThrowCUTReaderException(severity,tag) \ 331 { \ 332 if (palette != NULL) \ 333 palette=DestroyImage(palette); \ 334 if (clone_info != NULL) \ 335 clone_info=DestroyImageInfo(clone_info); \ 336 ThrowReaderException(severity,tag); \ 337 } 338 339 Image *image,*palette; 340 ImageInfo *clone_info; 341 MagickBooleanType status; 342 343 MagickOffsetType 344 offset; 345 346 size_t EncodedByte; 347 unsigned char RunCount,RunValue,RunCountMasked; 348 CUTHeader Header; 349 CUTPalHeader PalHeader; 350 ssize_t depth; 351 ssize_t i,j; 352 ssize_t ldblk; 353 unsigned char *BImgBuff=NULL,*ptrB; 354 register Quantum *q; 355 356 /* 357 Open image file. 358 */ 359 assert(image_info != (const ImageInfo *) NULL); 360 assert(image_info->signature == MagickCoreSignature); 361 if (image_info->debug != MagickFalse) 362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 363 image_info->filename); 364 assert(exception != (ExceptionInfo *) NULL); 365 assert(exception->signature == MagickCoreSignature); 366 image=AcquireImage(image_info,exception); 367 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 368 if (status == MagickFalse) 369 { 370 image=DestroyImageList(image); 371 return((Image *) NULL); 372 } 373 /* 374 Read CUT image. 375 */ 376 palette=NULL; 377 clone_info=NULL; 378 Header.Width=ReadBlobLSBShort(image); 379 Header.Height=ReadBlobLSBShort(image); 380 Header.Reserved=ReadBlobLSBShort(image); 381 382 if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0) 383 CUT_KO: ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader"); 384 385 /*---This code checks first line of image---*/ 386 EncodedByte=ReadBlobLSBShort(image); 387 RunCount=(unsigned char) ReadBlobByte(image); 388 RunCountMasked=RunCount & 0x7F; 389 ldblk=0; 390 while((int) RunCountMasked!=0) /*end of line?*/ 391 { 392 i=1; 393 if((int) RunCount<0x80) i=(ssize_t) RunCountMasked; 394 offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET); 395 if (offset < 0) 396 ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader"); 397 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/ 398 EncodedByte-=i+1; 399 ldblk+=(ssize_t) RunCountMasked; 400 401 RunCount=(unsigned char) ReadBlobByte(image); 402 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/ 403 RunCountMasked=RunCount & 0x7F; 404 } 405 if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/ 406 i=0; /*guess a number of bit planes*/ 407 if(ldblk==(int) Header.Width) i=8; 408 if(2*ldblk==(int) Header.Width) i=4; 409 if(8*ldblk==(int) Header.Width) i=1; 410 if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/ 411 depth=i; 412 413 image->columns=Header.Width; 414 image->rows=Header.Height; 415 image->depth=8; 416 image->colors=(size_t) (GetQuantumRange(1UL*i)+1); 417 418 if (image_info->ping != MagickFalse) goto Finish; 419 status=SetImageExtent(image,image->columns,image->rows,exception); 420 if (status == MagickFalse) 421 return(DestroyImageList(image)); 422 423 /* ----- Do something with palette ----- */ 424 if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette; 425 426 427 i=(ssize_t) strlen(clone_info->filename); 428 j=i; 429 while(--i>0) 430 { 431 if(clone_info->filename[i]=='.') 432 { 433 break; 434 } 435 if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' || 436 clone_info->filename[i]==':' ) 437 { 438 i=j; 439 break; 440 } 441 } 442 443 (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t) 444 (MagickPathExtent-i)); 445 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) 446 { 447 (void) CopyMagickString(clone_info->filename+i,".pal",(size_t) 448 (MagickPathExtent-i)); 449 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) 450 { 451 clone_info->filename[i]='\0'; 452 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) 453 { 454 clone_info=DestroyImageInfo(clone_info); 455 clone_info=NULL; 456 goto NoPalette; 457 } 458 } 459 } 460 461 if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette; 462 status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception); 463 if (status == MagickFalse) 464 { 465 ErasePalette: 466 palette=DestroyImage(palette); 467 palette=NULL; 468 goto NoPalette; 469 } 470 471 472 if(palette!=NULL) 473 { 474 (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId); 475 if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette; 476 PalHeader.Version=ReadBlobLSBShort(palette); 477 PalHeader.Size=ReadBlobLSBShort(palette); 478 PalHeader.FileType=(char) ReadBlobByte(palette); 479 PalHeader.SubType=(char) ReadBlobByte(palette); 480 PalHeader.BoardID=ReadBlobLSBShort(palette); 481 PalHeader.GraphicsMode=ReadBlobLSBShort(palette); 482 PalHeader.MaxIndex=ReadBlobLSBShort(palette); 483 PalHeader.MaxRed=ReadBlobLSBShort(palette); 484 PalHeader.MaxGreen=ReadBlobLSBShort(palette); 485 PalHeader.MaxBlue=ReadBlobLSBShort(palette); 486 (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId); 487 if (EOFBlob(image)) 488 ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile"); 489 490 if(PalHeader.MaxIndex<1) goto ErasePalette; 491 image->colors=PalHeader.MaxIndex+1; 492 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory; 493 494 if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/ 495 if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange; 496 if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange; 497 498 for(i=0;i<=(int) PalHeader.MaxIndex;i++) 499 { /*this may be wrong- I don't know why is palette such strange*/ 500 j=(ssize_t) TellBlob(palette); 501 if((j % 512)>512-6) 502 { 503 j=((j / 512)+1)*512; 504 offset=SeekBlob(palette,j,SEEK_SET); 505 if (offset < 0) 506 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 507 } 508 image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette); 509 if (QuantumRange != (Quantum) PalHeader.MaxRed) 510 { 511 image->colormap[i].red=ClampToQuantum(((double) 512 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/ 513 PalHeader.MaxRed); 514 } 515 image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette); 516 if (QuantumRange != (Quantum) PalHeader.MaxGreen) 517 { 518 image->colormap[i].green=ClampToQuantum 519 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen); 520 } 521 image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette); 522 if (QuantumRange != (Quantum) PalHeader.MaxBlue) 523 { 524 image->colormap[i].blue=ClampToQuantum 525 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue); 526 } 527 528 } 529 if (EOFBlob(image)) 530 ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile"); 531 } 532 533 534 535 NoPalette: 536 if(palette==NULL) 537 { 538 539 image->colors=256; 540 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 541 { 542 NoMemory: 543 ThrowCUTReaderException(ResourceLimitError,"MemoryAllocationFailed"); 544 } 545 546 for (i=0; i < (ssize_t)image->colors; i++) 547 { 548 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i); 549 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i); 550 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i); 551 } 552 } 553 554 555 /* ----- Load RLE compressed raster ----- */ 556 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk, 557 sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/ 558 if(BImgBuff==NULL) goto NoMemory; 559 560 offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET); 561 if (offset < 0) 562 { 563 if (palette != NULL) 564 palette=DestroyImage(palette); 565 if (clone_info != NULL) 566 clone_info=DestroyImageInfo(clone_info); 567 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff); 568 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 569 } 570 for (i=0; i < (int) Header.Height; i++) 571 { 572 EncodedByte=ReadBlobLSBShort(image); 573 574 ptrB=BImgBuff; 575 j=ldblk; 576 577 RunCount=(unsigned char) ReadBlobByte(image); 578 RunCountMasked=RunCount & 0x7F; 579 580 while ((int) RunCountMasked != 0) 581 { 582 if((ssize_t) RunCountMasked>j) 583 { /*Wrong Data*/ 584 RunCountMasked=(unsigned char) j; 585 if(j==0) 586 { 587 break; 588 } 589 } 590 591 if((int) RunCount>0x80) 592 { 593 RunValue=(unsigned char) ReadBlobByte(image); 594 (void) memset(ptrB,(int) RunValue,(size_t) RunCountMasked); 595 } 596 else { 597 (void) ReadBlob(image,(size_t) RunCountMasked,ptrB); 598 } 599 600 ptrB+=(int) RunCountMasked; 601 j-=(int) RunCountMasked; 602 603 if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */ 604 RunCount=(unsigned char) ReadBlobByte(image); 605 RunCountMasked=RunCount & 0x7F; 606 } 607 608 InsertRow(image,depth,BImgBuff,i,exception); 609 } 610 (void) SyncImage(image,exception); 611 612 613 /*detect monochrome image*/ 614 615 if(palette==NULL) 616 { /*attempt to detect binary (black&white) images*/ 617 if ((image->storage_class == PseudoClass) && 618 (SetImageGray(image,exception) != MagickFalse)) 619 { 620 if(GetCutColors(image,exception)==2) 621 { 622 for (i=0; i < (ssize_t)image->colors; i++) 623 { 624 register Quantum 625 sample; 626 sample=ScaleCharToQuantum((unsigned char) i); 627 if(image->colormap[i].red!=sample) goto Finish; 628 if(image->colormap[i].green!=sample) goto Finish; 629 if(image->colormap[i].blue!=sample) goto Finish; 630 } 631 632 image->colormap[1].red=image->colormap[1].green= 633 image->colormap[1].blue=QuantumRange; 634 for (i=0; i < (ssize_t)image->rows; i++) 635 { 636 q=QueueAuthenticPixels(image,0,i,image->columns,1,exception); 637 if (q == (Quantum *) NULL) 638 break; 639 for (j=0; j < (ssize_t)image->columns; j++) 640 { 641 if (GetPixelRed(image,q) == ScaleCharToQuantum(1)) 642 { 643 SetPixelRed(image,QuantumRange,q); 644 SetPixelGreen(image,QuantumRange,q); 645 SetPixelBlue(image,QuantumRange,q); 646 } 647 q+=GetPixelChannels(image); 648 } 649 if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish; 650 } 651 } 652 } 653 } 654 655 Finish: 656 if (BImgBuff != NULL) 657 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff); 658 if (palette != NULL) 659 palette=DestroyImage(palette); 660 if (clone_info != NULL) 661 clone_info=DestroyImageInfo(clone_info); 662 if (EOFBlob(image) != MagickFalse) 663 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 664 image->filename); 665 (void) CloseBlob(image); 666 return(GetFirstImageInList(image)); 667 } 668 669 /* 671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 672 % % 673 % % 674 % % 675 % R e g i s t e r C U T I m a g e % 676 % % 677 % % 678 % % 679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 680 % 681 % RegisterCUTImage() adds attributes for the CUT image format to 682 % the list of supported formats. The attributes include the image format 683 % tag, a method to read and/or write the format, whether the format 684 % supports the saving of more than one frame to the same file or blob, 685 % whether the format supports native in-memory I/O, and a brief 686 % description of the format. 687 % 688 % The format of the RegisterCUTImage method is: 689 % 690 % size_t RegisterCUTImage(void) 691 % 692 */ 693 ModuleExport size_t RegisterCUTImage(void) 694 { 695 MagickInfo 696 *entry; 697 698 entry=AcquireMagickInfo("CUT","CUT","DR Halo"); 699 entry->decoder=(DecodeImageHandler *) ReadCUTImage; 700 entry->flags|=CoderDecoderSeekableStreamFlag; 701 (void) RegisterMagickInfo(entry); 702 return(MagickImageCoderSignature); 703 } 704 705 /* 707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 708 % % 709 % % 710 % % 711 % U n r e g i s t e r C U T I m a g e % 712 % % 713 % % 714 % % 715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 716 % 717 % UnregisterCUTImage() removes format registrations made by the 718 % CUT module from the list of supported formats. 719 % 720 % The format of the UnregisterCUTImage method is: 721 % 722 % UnregisterCUTImage(void) 723 % 724 */ 725 ModuleExport void UnregisterCUTImage(void) 726 { 727 (void) UnregisterMagickInfo("CUT"); 728 } 729