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