rgb.c revision 5ffcab561963e799f33e8ae3fec6faac948825a5
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% RRRR GGGG BBBB % 7% R R G B B % 8% RRRR G GG BBBB % 9% R R G G B B % 10% R R GGG BBBB % 11% % 12% % 13% Read/Write Raw RGB Image Format % 14% % 15% Software Design % 16% John Cristy % 17% July 1992 % 18% % 19% % 20% Copyright 1999-2008 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 "magick/studio.h" 43#include "magick/blob.h" 44#include "magick/blob-private.h" 45#include "magick/cache.h" 46#include "magick/colorspace.h" 47#include "magick/constitute.h" 48#include "magick/exception.h" 49#include "magick/exception-private.h" 50#include "magick/image.h" 51#include "magick/image-private.h" 52#include "magick/list.h" 53#include "magick/magick.h" 54#include "magick/memory_.h" 55#include "magick/monitor.h" 56#include "magick/monitor-private.h" 57#include "magick/pixel-private.h" 58#include "magick/quantum-private.h" 59#include "magick/static.h" 60#include "magick/statistic.h" 61#include "magick/string_.h" 62#include "magick/module.h" 63#include "magick/utility.h" 64 65/* 66 Forward declarations. 67*/ 68static MagickBooleanType 69 WriteRGBImage(const ImageInfo *,Image *); 70 71/* 72%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73% % 74% % 75% % 76% R e a d R G B I m a g e % 77% % 78% % 79% % 80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81% 82% ReadRGBImage() reads an image of raw RGB or RGBA samples and returns it. It 83% allocates the memory necessary for the new Image structure and returns a 84% pointer to the new image. 85% 86% The format of the ReadRGBImage method is: 87% 88% Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception) 89% 90% A description of each parameter follows: 91% 92% o image_info: the image info. 93% 94% o exception: return any errors or warnings in this structure. 95% 96*/ 97static Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception) 98{ 99 Image 100 *canvas_image, 101 *image; 102 103 long 104 y; 105 106 MagickBooleanType 107 status; 108 109 MagickOffsetType 110 scene; 111 112 QuantumInfo 113 *quantum_info; 114 115 QuantumType 116 quantum_type; 117 118 register long 119 i, 120 j; 121 122 Quantum 123 qx[3]; 124 125 ssize_t 126 count; 127 128 size_t 129 length; 130 131 unsigned char 132 *pixels; 133 134 QuantumType 135 quantum_types[4]; 136 137 char 138 sfx[] = {0, 0}; 139 140 int 141 channels = 3; 142 143 /* 144 Open image file. 145 */ 146 assert(image_info != (const ImageInfo *) NULL); 147 assert(image_info->signature == MagickSignature); 148 if (image_info->debug != MagickFalse) 149 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 150 image_info->filename); 151 assert(exception != (ExceptionInfo *) NULL); 152 assert(exception->signature == MagickSignature); 153 image=AcquireImage(image_info); 154 if ((image->columns == 0) || (image->rows == 0)) 155 ThrowReaderException(OptionError,"MustSpecifyImageSize"); 156 if (image_info->interlace != PartitionInterlace) 157 { 158 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 159 if (status == MagickFalse) 160 { 161 image=DestroyImageList(image); 162 return((Image *) NULL); 163 } 164 for (i=0; i < image->offset; i++) 165 if (ReadBlobByte(image) == EOF) 166 { 167 ThrowFileException(exception,CorruptImageError, 168 "UnexpectedEndOfFile",image->filename); 169 break; 170 } 171 } 172 /* 173 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]). 174 */ 175 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse, 176 exception); 177 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod); 178 quantum_info=AcquireQuantumInfo(image_info,canvas_image); 179 if (quantum_info == (QuantumInfo *) NULL) 180 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 181 pixels=GetQuantumPixels(quantum_info); 182 quantum_type=RGBQuantum; 183 if (LocaleCompare(image_info->magick,"RGBA") == 0) 184 { 185 quantum_type=RGBAQuantum; 186 image->matte=MagickTrue; 187 channels=4; 188 } 189 if (LocaleCompare(image_info->magick,"RGBO") == 0) 190 { 191 quantum_type=RGBOQuantum; 192 image->matte=MagickTrue; 193 channels=4; 194 } 195 if (image_info->number_scenes != 0) 196 while (image->scene < image_info->scene) 197 { 198 /* 199 Skip to next image. 200 */ 201 image->scene++; 202 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type); 203 for (y=0; y < (long) image->rows; y++) 204 { 205 count=ReadBlob(image,length,pixels); 206 if (count != (ssize_t) length) 207 break; 208 } 209 } 210 for (i=0; i < channels; i++) 211 { 212 switch(image_info->magick[i]) 213 { 214 case 'R': quantum_types[i]=RedQuantum; break; 215 case 'G': quantum_types[i]=GreenQuantum; break; 216 case 'B': quantum_types[i]=BlueQuantum; break; 217 case 'A': quantum_types[i]=AlphaQuantum; break; 218 case 'O': quantum_types[i]=OpacityQuantum; break; 219 } 220 } 221 count=0; 222 length=0; 223 scene=0; 224 do 225 { 226 /* 227 Read pixels to virtual canvas image then push to image. 228 */ 229 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 230 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 231 break; 232 switch (image_info->interlace) 233 { 234 case NoInterlace: 235 default: 236 { 237 /* 238 No interlacing: RGBRGBRGBRGBRGBRGB... 239 */ 240 if (scene == 0) 241 { 242 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type); 243 count=ReadBlob(image,length,pixels); 244 if (count != (ssize_t) length) 245 break; 246 } 247 for (y=0; y < (long) image->extract_info.height; y++) 248 { 249 register const PixelPacket 250 *__restrict p; 251 252 register long 253 x; 254 255 register PixelPacket 256 *__restrict q; 257 258 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1, 259 exception); 260 if (q == (PixelPacket *) NULL) 261 break; 262 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL, 263 quantum_info,quantum_type,pixels,exception); 264 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse) 265 break; 266 if (((y-image->extract_info.y) >= 0) && 267 ((y-image->extract_info.y) < (long) image->rows)) 268 { 269 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0, 270 canvas_image->columns,1,exception); 271 q=QueueAuthenticPixels(image,0,y-image->extract_info.y, 272 image->columns,1,exception); 273 if ((p == (const PixelPacket *) NULL) || 274 (q == (PixelPacket *) NULL)) 275 break; 276 for (x=0; x < (long) image->columns; x++) 277 { 278 qx[0]=p->red; 279 qx[1]=p->green; 280 qx[2]=p->blue; 281 for (i=0; i < 3; i++) 282 switch(quantum_types[i]) 283 { 284 case RedQuantum: q->red=qx[i]; break; 285 case GreenQuantum: q->green=qx[i]; break; 286 case BlueQuantum: q->blue=qx[i]; break; 287 default: break; 288 } 289 q->opacity=OpaqueOpacity; 290 if (image->matte != MagickFalse) 291 q->opacity=p->opacity; 292 p++; 293 q++; 294 } 295 if (SyncAuthenticPixels(image,exception) == MagickFalse) 296 break; 297 } 298 if (image->previous == (Image *) NULL) 299 { 300 status=SetImageProgress(image,LoadImageTag,y,image->rows); 301 if (status == MagickFalse) 302 break; 303 } 304 count=ReadBlob(image,length,pixels); 305 if (count != (ssize_t) length) 306 break; 307 } 308 break; 309 } 310 case LineInterlace: 311 { 312 /* 313 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB... 314 */ 315 if (scene == 0) 316 { 317 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[0]); 318 count=ReadBlob(image,length,pixels); 319 if (count != (ssize_t) length) 320 break; 321 } 322 for (y=0; y < (long) image->extract_info.height; y++) 323 { 324 register const PixelPacket 325 *__restrict p; 326 327 register long 328 x; 329 330 register PixelPacket 331 *__restrict q; 332 333 for (i=0; i < channels; i++) 334 { 335 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1, 336 exception); 337 if (q == (PixelPacket *) NULL) 338 break; 339 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL, 340 quantum_info,quantum_types[i],pixels,exception); 341 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse) 342 break; 343 if (((y-image->extract_info.y) >= 0) && 344 ((y-image->extract_info.y) < (long) image->rows)) 345 { 346 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x, 347 0,canvas_image->columns,1,exception); 348 q=GetAuthenticPixels(image,0,y-image->extract_info.y, 349 image->columns,1,exception); 350 if ((p == (const PixelPacket *) NULL) || 351 (q == (PixelPacket *) NULL)) 352 break; 353 if (i == (channels - 1)) 354 for (x=0; x < (long) image->columns; x++) 355 { 356 q->red=p->red; 357 q->green=p->green; 358 q->blue=p->blue; 359 q->opacity=p->opacity; 360 p++; 361 q++; 362 } 363 if (SyncAuthenticPixels(image,exception) == MagickFalse) 364 break; 365 } 366 count=ReadBlob(image,length,pixels); 367 if (count != (ssize_t) length) 368 break; 369 } 370 if (image->previous == (Image *) NULL) 371 { 372 status=SetImageProgress(image,LoadImageTag,y,image->rows); 373 if (status == MagickFalse) 374 break; 375 } 376 } 377 break; 378 } 379 case PlaneInterlace: 380 { 381 /* 382 Plane interlacing: RRRRRR...GGGGGG...BBBBBB... 383 */ 384 if (scene == 0) 385 { 386 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[0]); 387 count=ReadBlob(image,length,pixels); 388 if (count != (ssize_t) length) 389 break; 390 } 391 for (i=0; i < channels; i++) 392 { 393 for (y=0; y < (long) image->extract_info.height; y++) 394 { 395 register const PixelPacket 396 *__restrict p; 397 398 register long 399 x; 400 401 register PixelPacket 402 *__restrict q; 403 404 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1, 405 exception); 406 if (q == (PixelPacket *) NULL) 407 break; 408 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL, 409 quantum_info,quantum_types[i],pixels,exception); 410 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse) 411 break; 412 if (((y-image->extract_info.y) >= 0) && 413 ((y-image->extract_info.y) < (long) image->rows)) 414 { 415 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0, 416 canvas_image->columns,1,exception); 417 q=GetAuthenticPixels(image,0,y-image->extract_info.y, 418 image->columns,1,exception); 419 if ((p == (const PixelPacket *) NULL) || 420 (q == (PixelPacket *) NULL)) 421 break; 422 for (x=0; x < (long) image->columns; x++) 423 { 424 switch(quantum_types[i]) 425 { 426 case RedQuantum: q->red=p->red; break; 427 case GreenQuantum: q->green=p->green; break; 428 case BlueQuantum: q->blue=p->blue; break; 429 case OpacityQuantum: 430 case AlphaQuantum: q->opacity=p->opacity; break; 431 default: break; 432 } 433 p++; 434 q++; 435 } 436 if (SyncAuthenticPixels(image,exception) == MagickFalse) 437 break; 438 } 439 count=ReadBlob(image,length,pixels); 440 if (count != (ssize_t) length) 441 break; 442 } 443 if (image->previous == (Image *) NULL) 444 { 445 status=SetImageProgress(image,LoadImageTag,(i+1),5); 446 if (status == MagickFalse) 447 break; 448 } 449 } 450 if (image->previous == (Image *) NULL) 451 { 452 status=SetImageProgress(image,LoadImageTag,5,5); 453 if (status == MagickFalse) 454 break; 455 } 456 break; 457 } 458 case PartitionInterlace: 459 { 460 /* 461 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB... 462 */ 463 for (i=0; i < channels; i++) 464 { 465 sfx[0]=image_info->magick[i]; 466 AppendImageFormat(sfx,image->filename); 467 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 468 if (status == MagickFalse) 469 { 470 canvas_image=DestroyImageList(canvas_image); 471 image=DestroyImageList(image); 472 return((Image *) NULL); 473 } 474 if (i == 0) 475 for (j=0; j < image->offset; j++) 476 if (ReadBlobByte(image) == EOF) 477 { 478 ThrowFileException(exception,CorruptImageError, 479 "UnexpectedEndOfFile",image->filename); 480 break; 481 } 482 length=GetQuantumExtent(canvas_image,quantum_info,quantum_types[i]); 483 for (j=0; j < (long) scene; j++) 484 for (y=0; y < (long) image->extract_info.height; y++) 485 if (ReadBlob(image,length,pixels) != (ssize_t) length) 486 { 487 ThrowFileException(exception,CorruptImageError, 488 "UnexpectedEndOfFile",image->filename); 489 break; 490 } 491 count=ReadBlob(image,length,pixels); 492 if (count != (ssize_t) length) 493 break; 494 for (y=0; y < (long) image->extract_info.height; y++) 495 { 496 register const PixelPacket 497 *__restrict p; 498 499 register long 500 x; 501 502 register PixelPacket 503 *__restrict q; 504 505 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1, 506 exception); 507 if (q == (PixelPacket *) NULL) 508 break; 509 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL, 510 quantum_info,quantum_types[i],pixels,exception); 511 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse) 512 break; 513 if (((y-image->extract_info.y) >= 0) && 514 ((y-image->extract_info.y) < (long) image->rows)) 515 { 516 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0, 517 canvas_image->columns,1,exception); 518 q=GetAuthenticPixels(image,0,y-image->extract_info.y, 519 image->columns,1,exception); 520 if ((p == (const PixelPacket *) NULL) || 521 (q == (PixelPacket *) NULL)) 522 break; 523 for (x=0; x < (long) image->columns; x++) 524 { 525 switch(quantum_types[i]) 526 { 527 case RedQuantum: q->red=p->red; break; 528 case GreenQuantum: q->green=p->green; break; 529 case BlueQuantum: q->blue=p->blue; break; 530 case OpacityQuantum: 531 case AlphaQuantum: q->opacity=p->opacity; break; 532 default: break; 533 } 534 p++; 535 q++; 536 } 537 if (SyncAuthenticPixels(image,exception) == MagickFalse) 538 break; 539 } 540 count=ReadBlob(image,length,pixels); 541 if (count != (ssize_t) length) 542 break; 543 } 544 if (image->previous == (Image *) NULL) 545 { 546 status=SetImageProgress(image,LoadImageTag,(i+1),5); 547 if (status == MagickFalse) 548 break; 549 } 550 if (i != (channels-1)) 551 (void) CloseBlob(image); 552 } 553 if (image->previous == (Image *) NULL) 554 { 555 status=SetImageProgress(image,LoadImageTag,5,5); 556 if (status == MagickFalse) 557 break; 558 } 559 break; 560 } 561 } 562 SetQuantumImageType(image,quantum_type); 563 /* 564 Proceed to next image. 565 */ 566 if (image_info->number_scenes != 0) 567 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 568 break; 569 if (count == (ssize_t) length) 570 { 571 /* 572 Allocate next image structure. 573 */ 574 AcquireNextImage(image_info,image); 575 if (GetNextImageInList(image) == (Image *) NULL) 576 { 577 image=DestroyImageList(image); 578 return((Image *) NULL); 579 } 580 image=SyncNextImageInList(image); 581 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 582 GetBlobSize(image)); 583 if (status == MagickFalse) 584 break; 585 } 586 scene++; 587 } while (count == (ssize_t) length); 588 InheritException(exception,&image->exception); 589 quantum_info=DestroyQuantumInfo(quantum_info); 590 canvas_image=DestroyImage(canvas_image); 591 (void) CloseBlob(image); 592 return(GetFirstImageInList(image)); 593} 594 595/* 596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 597% % 598% % 599% % 600% R e g i s t e r R G B I m a g e % 601% % 602% % 603% % 604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 605% 606% RegisterRGBImage() adds attributes for the RGB or RGBA image format to 607% the list of supported formats. The attributes include the image format 608% tag, a method to read and/or write the format, whether the format 609% supports the saving of more than one frame to the same file or blob, 610% whether the format supports native in-memory I/O, and a brief 611% description of the format. 612% 613% The format of the RegisterRGBImage method is: 614% 615% unsigned long RegisterRGBImage(void) 616% 617*/ 618ModuleExport unsigned long RegisterRGBImage(void) 619{ 620 MagickInfo 621 *entry; 622 623 entry=SetMagickInfo("RGB"); 624 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 625 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 626 entry->raw=MagickTrue; 627 entry->endian_support=MagickTrue; 628 entry->format_type=ExplicitFormatType; 629 entry->description=ConstantString("Raw red, green, and blue samples"); 630 entry->module=ConstantString("RGB"); 631 (void) RegisterMagickInfo(entry); 632 entry=SetMagickInfo("RBG"); 633 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 634 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 635 entry->raw=MagickTrue; 636 entry->endian_support=MagickTrue; 637 entry->format_type=ExplicitFormatType; 638 entry->description=ConstantString("Raw red, blue, and green samples"); 639 entry->module=ConstantString("RGB"); 640 (void) RegisterMagickInfo(entry); 641 entry=SetMagickInfo("GRB"); 642 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 643 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 644 entry->raw=MagickTrue; 645 entry->endian_support=MagickTrue; 646 entry->format_type=ExplicitFormatType; 647 entry->description=ConstantString("Raw green, red, and blue samples"); 648 entry->module=ConstantString("RGB"); 649 (void) RegisterMagickInfo(entry); 650 entry=SetMagickInfo("GBR"); 651 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 652 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 653 entry->raw=MagickTrue; 654 entry->endian_support=MagickTrue; 655 entry->format_type=ExplicitFormatType; 656 entry->description=ConstantString("Raw green, blue, and red samples"); 657 entry->module=ConstantString("RGB"); 658 (void) RegisterMagickInfo(entry); 659 entry=SetMagickInfo("BRG"); 660 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 661 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 662 entry->raw=MagickTrue; 663 entry->endian_support=MagickTrue; 664 entry->format_type=ExplicitFormatType; 665 entry->description=ConstantString("Raw blue, red, and green samples"); 666 entry->module=ConstantString("RGB"); 667 (void) RegisterMagickInfo(entry); 668 entry=SetMagickInfo("BGR"); 669 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 670 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 671 entry->raw=MagickTrue; 672 entry->endian_support=MagickTrue; 673 entry->format_type=ExplicitFormatType; 674 entry->description=ConstantString("Raw blue, green, and red samples"); 675 entry->module=ConstantString("RGB"); 676 (void) RegisterMagickInfo(entry); 677 entry=SetMagickInfo("RGBA"); 678 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 679 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 680 entry->raw=MagickTrue; 681 entry->endian_support=MagickTrue; 682 entry->format_type=ExplicitFormatType; 683 entry->description=ConstantString("Raw red, green, blue, and alpha samples"); 684 entry->module=ConstantString("RGB"); 685 (void) RegisterMagickInfo(entry); 686 entry=SetMagickInfo("RGBO"); 687 entry->decoder=(DecodeImageHandler *) ReadRGBImage; 688 entry->encoder=(EncodeImageHandler *) WriteRGBImage; 689 entry->raw=MagickTrue; 690 entry->endian_support=MagickTrue; 691 entry->format_type=ExplicitFormatType; 692 entry->description=ConstantString("Raw red, green, blue, and opacity " 693 "samples"); 694 entry->module=ConstantString("RGB"); 695 (void) RegisterMagickInfo(entry); 696 return(MagickImageCoderSignature); 697} 698 699/* 700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 701% % 702% % 703% % 704% U n r e g i s t e r R G B I m a g e % 705% % 706% % 707% % 708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 709% 710% UnregisterRGBImage() removes format registrations made by the 711% RGB module from the list of supported formats. 712% 713% The format of the UnregisterRGBImage method is: 714% 715% UnregisterRGBImage(void) 716% 717*/ 718ModuleExport void UnregisterRGBImage(void) 719{ 720 (void) UnregisterMagickInfo("RGBO"); 721 (void) UnregisterMagickInfo("RGBA"); 722 (void) UnregisterMagickInfo("BGR"); 723 (void) UnregisterMagickInfo("BRG"); 724 (void) UnregisterMagickInfo("GBR"); 725 (void) UnregisterMagickInfo("GRB"); 726 (void) UnregisterMagickInfo("RBG"); 727 (void) UnregisterMagickInfo("RGB"); 728} 729 730/* 731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 732% % 733% % 734% % 735% W r i t e R G B I m a g e % 736% % 737% % 738% % 739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 740% 741% WriteRGBImage() writes an image to a file in the RGB or RGBA rasterfile 742% format. 743% 744% The format of the WriteRGBImage method is: 745% 746% MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image) 747% 748% A description of each parameter follows. 749% 750% o image_info: the image info. 751% 752% o image: The image. 753% 754*/ 755static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image) 756{ 757 long 758 y; 759 760 MagickBooleanType 761 status; 762 763 MagickOffsetType 764 scene; 765 766 QuantumInfo 767 *quantum_info; 768 769 QuantumType 770 quantum_type, 771 quantum_types[4]; 772 773 register long 774 i; 775 776 ssize_t 777 count; 778 779 size_t 780 length; 781 782 unsigned char 783 *pixels; 784 785 unsigned long 786 channels; 787 788 /* 789 Allocate memory for pixels. 790 */ 791 assert(image_info != (const ImageInfo *) NULL); 792 assert(image_info->signature == MagickSignature); 793 assert(image != (Image *) NULL); 794 assert(image->signature == MagickSignature); 795 if (image->debug != MagickFalse) 796 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 797 if (image_info->interlace != PartitionInterlace) 798 { 799 /* 800 Open output image file. 801 */ 802 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 803 if (status == MagickFalse) 804 return(status); 805 } 806 quantum_type=RGBQuantum; 807 channels=3; 808 if (LocaleCompare(image_info->magick,"RGBA") == 0) 809 { 810 quantum_type=RGBAQuantum; 811 image->matte=MagickTrue; 812 channels=4; 813 } 814 if (LocaleCompare(image_info->magick,"RGBO") == 0) 815 { 816 quantum_type=RGBOQuantum; 817 image->matte=MagickTrue; 818 channels=4; 819 } 820 for (i=0; i < (long) channels; i++) 821 { 822 switch (image_info->magick[i]) 823 { 824 case 'R': quantum_types[i]=RedQuantum; break; 825 case 'G': quantum_types[i]=GreenQuantum; break; 826 case 'B': quantum_types[i]=BlueQuantum; break; 827 case 'A': quantum_types[i]=AlphaQuantum; break; 828 case 'O': quantum_types[i]=OpacityQuantum; break; 829 } 830 } 831 scene=0; 832 do 833 { 834 /* 835 Convert MIFF to RGB raster pixels. 836 */ 837 if (image->colorspace != RGBColorspace) 838 (void) TransformImageColorspace(image,RGBColorspace); 839 if ((LocaleCompare(image_info->magick,"RGBA") == 0) && 840 (image->matte == MagickFalse)) 841 (void) SetImageAlphaChannel(image,ResetAlphaChannel); 842 quantum_info=AcquireQuantumInfo(image_info,image); 843 if (quantum_info == (QuantumInfo *) NULL) 844 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 845 pixels=GetQuantumPixels(quantum_info); 846 switch (image_info->interlace) 847 { 848 case NoInterlace: 849 default: 850 { 851 CacheView 852 *image_view; 853 854 PixelPacket 855 px; 856 857 Quantum 858 *qx[3]; 859 860 /* 861 No interlacing: RGBRGBRGBRGBRGBRGB... 862 */ 863 image_view=AcquireCacheView(image); 864 for (y=0; y < (long) image->rows; y++) 865 { 866 register long 867 x; 868 869 register PixelPacket 870 *__restrict q; 871 872 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1, 873 &image->exception); 874 if (q == (PixelPacket *) NULL) 875 break; 876 for (x=0; x < (long) image->columns; x++) 877 { 878 px=(*q); 879 qx[0]=&(q->red); 880 qx[1]=&(q->green); 881 qx[2]=&(q->blue); 882 for (i=0; i < 3; i++) 883 switch (quantum_types[i]) 884 { 885 case RedQuantum: *qx[i]=px.red; break; 886 case GreenQuantum: *qx[i]=px.green; break; 887 case BlueQuantum: *qx[i]=px.blue; break; 888 default: break; 889 } 890 q++; 891 } 892 length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type, 893 pixels,&image->exception); 894 count=WriteBlob(image,length,pixels); 895 if (count != (ssize_t) length) 896 break; 897 if (image->previous == (Image *) NULL) 898 { 899 status=SetImageProgress(image,SaveImageTag,y,image->rows); 900 if (status == MagickFalse) 901 break; 902 } 903 } 904 image_view=DestroyCacheView(image_view); 905 break; 906 } 907 case LineInterlace: 908 { 909 /* 910 Line interlacing: RRR...GGG...BBB...RRR...GGG...BBB... 911 */ 912 for (y=0; y < (long) image->rows; y++) 913 { 914 register const PixelPacket 915 *__restrict p; 916 917 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 918 if (p == (const PixelPacket *) NULL) 919 break; 920 for (i=0; i < (long) channels; i++) 921 { 922 length=ExportQuantumPixels(image,(const CacheView *) NULL, 923 quantum_info,quantum_types[i],pixels,&image->exception); 924 count=WriteBlob(image,length,pixels); 925 if (count != (ssize_t) length) 926 break; 927 } 928 if (image->previous == (Image *) NULL) 929 { 930 status=SetImageProgress(image,SaveImageTag,y,image->rows); 931 if (status == MagickFalse) 932 break; 933 } 934 } 935 break; 936 } 937 case PlaneInterlace: 938 { 939 /* 940 Plane interlacing: RRRRRR...GGGGGG...BBBBBB... 941 */ 942 for (i=0; i < (long) channels; i++) 943 { 944 for (y=0; y < (long) image->rows; y++) 945 { 946 register const PixelPacket 947 *__restrict p; 948 949 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 950 if (p == (const PixelPacket *) NULL) 951 break; 952 length=ExportQuantumPixels(image,(const CacheView *) NULL, 953 quantum_info,quantum_types[i],pixels,&image->exception); 954 count=WriteBlob(image,length,pixels); 955 if (count != (ssize_t) length) 956 break; 957 } 958 if (image->previous == (Image *) NULL) 959 { 960 status=SetImageProgress(image,SaveImageTag,(i+1),5); 961 if (status == MagickFalse) 962 break; 963 } 964 } 965 if (image->previous == (Image *) NULL) 966 { 967 status=SetImageProgress(image,SaveImageTag,5,5); 968 if (status == MagickFalse) 969 break; 970 } 971 break; 972 } 973 case PartitionInterlace: 974 { 975 char 976 sfx[] = {0, 0}; 977 978 /* 979 Partition interlacing: RRRRRR..., GGGGGG..., BBBBBB... 980 */ 981 for (i=0; i < (long) channels; i++) 982 { 983 sfx[0]=image_info->magick[i]; 984 AppendImageFormat(sfx,image->filename); 985 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode : 986 AppendBinaryBlobMode,&image->exception); 987 if (status == MagickFalse) 988 return(status); 989 for (y=0; y < (long) image->rows; y++) 990 { 991 register const PixelPacket 992 *__restrict p; 993 994 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 995 if (p == (const PixelPacket *) NULL) 996 break; 997 length=ExportQuantumPixels(image,(const CacheView *) NULL, 998 quantum_info,quantum_types[i],pixels,&image->exception); 999 count=WriteBlob(image,length,pixels); 1000 if (count != (ssize_t) length) 1001 break; 1002 } 1003 if (image->previous == (Image *) NULL) 1004 { 1005 status=SetImageProgress(image,SaveImageTag,(i+1),5); 1006 if (status == MagickFalse) 1007 break; 1008 } 1009 (void) CloseBlob(image); 1010 } 1011 (void) CopyMagickString(image->filename,image_info->filename, 1012 MaxTextExtent); 1013 if (image->previous == (Image *) NULL) 1014 { 1015 status=SetImageProgress(image,SaveImageTag,5,5); 1016 if (status == MagickFalse) 1017 break; 1018 } 1019 break; 1020 } 1021 } 1022 quantum_info=DestroyQuantumInfo(quantum_info); 1023 if (GetNextImageInList(image) == (Image *) NULL) 1024 break; 1025 image=SyncNextImageInList(image); 1026 status=SetImageProgress(image,SaveImagesTag,scene++, 1027 GetImageListLength(image)); 1028 if (status == MagickFalse) 1029 break; 1030 } while (image_info->adjoin != MagickFalse); 1031 (void) CloseBlob(image); 1032 return(MagickTrue); 1033} 1034