viff.c revision acabb847a592ca5e430c1c0949d03acfc0b78bb9
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% V V IIIII FFFFF FFFFF % 7% V V I F F % 8% V V I FFF FFF % 9% V V I F F % 10% V IIIII F F % 11% % 12% % 13% Read/Write Khoros Visualization Image Format % 14% % 15% Software Design % 16% Cristy % 17% July 1992 % 18% % 19% % 20% Copyright 1999-2015 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 "MagickCore/studio.h" 43#include "MagickCore/attribute.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/cache.h" 47#include "MagickCore/color.h" 48#include "MagickCore/color-private.h" 49#include "MagickCore/colormap.h" 50#include "MagickCore/colormap-private.h" 51#include "MagickCore/colorspace.h" 52#include "MagickCore/colorspace-private.h" 53#include "MagickCore/exception.h" 54#include "MagickCore/exception-private.h" 55#include "MagickCore/image.h" 56#include "MagickCore/image-private.h" 57#include "MagickCore/list.h" 58#include "MagickCore/magick.h" 59#include "MagickCore/memory_.h" 60#include "MagickCore/monitor.h" 61#include "MagickCore/monitor-private.h" 62#include "MagickCore/pixel-accessor.h" 63#include "MagickCore/property.h" 64#include "MagickCore/quantum-private.h" 65#include "MagickCore/static.h" 66#include "MagickCore/string_.h" 67#include "MagickCore/module.h" 68 69/* 70 Forward declarations. 71*/ 72static MagickBooleanType 73 WriteVIFFImage(const ImageInfo *,Image *,ExceptionInfo *); 74 75/* 76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77% % 78% % 79% % 80% I s V I F F % 81% % 82% % 83% % 84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85% 86% IsVIFF() returns MagickTrue if the image format type, identified by the 87% magick string, is VIFF. 88% 89% The format of the IsVIFF method is: 90% 91% MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length) 92% 93% A description of each parameter follows: 94% 95% o magick: compare image format pattern against these bytes. 96% 97% o length: Specifies the length of the magick string. 98% 99*/ 100static MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length) 101{ 102 if (length < 2) 103 return(MagickFalse); 104 if (memcmp(magick,"\253\001",2) == 0) 105 return(MagickTrue); 106 return(MagickFalse); 107} 108 109/* 110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 111% % 112% % 113% % 114% R e a d V I F F I m a g e % 115% % 116% % 117% % 118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 119% 120% ReadVIFFImage() reads a Khoros Visualization image file and returns 121% it. It allocates the memory necessary for the new Image structure and 122% returns a pointer to the new image. 123% 124% The format of the ReadVIFFImage method is: 125% 126% Image *ReadVIFFImage(const ImageInfo *image_info, 127% ExceptionInfo *exception) 128% 129% A description of each parameter follows: 130% 131% o image: Method ReadVIFFImage returns a pointer to the image after 132% reading. A null image is returned if there is a memory shortage or if 133% the image cannot be read. 134% 135% o image_info: the image info. 136% 137% o exception: return any errors or warnings in this structure. 138% 139*/ 140static Image *ReadVIFFImage(const ImageInfo *image_info, 141 ExceptionInfo *exception) 142{ 143#define VFF_CM_genericRGB 15 144#define VFF_CM_ntscRGB 1 145#define VFF_CM_NONE 0 146#define VFF_DEP_DECORDER 0x4 147#define VFF_DEP_NSORDER 0x8 148#define VFF_DES_RAW 0 149#define VFF_LOC_IMPLICIT 1 150#define VFF_MAPTYP_NONE 0 151#define VFF_MAPTYP_1_BYTE 1 152#define VFF_MAPTYP_2_BYTE 2 153#define VFF_MAPTYP_4_BYTE 4 154#define VFF_MAPTYP_FLOAT 5 155#define VFF_MAPTYP_DOUBLE 7 156#define VFF_MS_NONE 0 157#define VFF_MS_ONEPERBAND 1 158#define VFF_MS_SHARED 3 159#define VFF_TYP_BIT 0 160#define VFF_TYP_1_BYTE 1 161#define VFF_TYP_2_BYTE 2 162#define VFF_TYP_4_BYTE 4 163#define VFF_TYP_FLOAT 5 164#define VFF_TYP_DOUBLE 9 165 166 typedef struct _ViffInfo 167 { 168 unsigned char 169 identifier, 170 file_type, 171 release, 172 version, 173 machine_dependency, 174 reserve[3]; 175 176 char 177 comment[512]; 178 179 unsigned int 180 rows, 181 columns, 182 subrows; 183 184 int 185 x_offset, 186 y_offset; 187 188 float 189 x_bits_per_pixel, 190 y_bits_per_pixel; 191 192 unsigned int 193 location_type, 194 location_dimension, 195 number_of_images, 196 number_data_bands, 197 data_storage_type, 198 data_encode_scheme, 199 map_scheme, 200 map_storage_type, 201 map_rows, 202 map_columns, 203 map_subrows, 204 map_enable, 205 maps_per_cycle, 206 color_space_model; 207 } ViffInfo; 208 209 double 210 min_value, 211 scale_factor, 212 value; 213 214 Image 215 *image; 216 217 int 218 bit; 219 220 MagickBooleanType 221 status; 222 223 MagickSizeType 224 number_pixels; 225 226 register ssize_t 227 x; 228 229 register Quantum 230 *q; 231 232 register ssize_t 233 i; 234 235 register unsigned char 236 *p; 237 238 size_t 239 bytes_per_pixel, 240 lsb_first, 241 max_packets, 242 quantum; 243 244 ssize_t 245 count, 246 y; 247 248 unsigned char 249 *pixels; 250 251 ViffInfo 252 viff_info; 253 254 /* 255 Open image file. 256 */ 257 assert(image_info != (const ImageInfo *) NULL); 258 assert(image_info->signature == MagickSignature); 259 if (image_info->debug != MagickFalse) 260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 261 image_info->filename); 262 assert(exception != (ExceptionInfo *) NULL); 263 assert(exception->signature == MagickSignature); 264 image=AcquireImage(image_info,exception); 265 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 266 if (status == MagickFalse) 267 { 268 image=DestroyImageList(image); 269 return((Image *) NULL); 270 } 271 /* 272 Read VIFF header (1024 bytes). 273 */ 274 count=ReadBlob(image,1,&viff_info.identifier); 275 do 276 { 277 /* 278 Verify VIFF identifier. 279 */ 280 if ((count == 0) || ((unsigned char) viff_info.identifier != 0xab)) 281 ThrowReaderException(CorruptImageError,"NotAVIFFImage"); 282 /* 283 Initialize VIFF image. 284 */ 285 (void) ReadBlob(image,sizeof(viff_info.file_type),&viff_info.file_type); 286 (void) ReadBlob(image,sizeof(viff_info.release),&viff_info.release); 287 (void) ReadBlob(image,sizeof(viff_info.version),&viff_info.version); 288 (void) ReadBlob(image,sizeof(viff_info.machine_dependency), 289 &viff_info.machine_dependency); 290 (void) ReadBlob(image,sizeof(viff_info.reserve),viff_info.reserve); 291 count=ReadBlob(image,512,(unsigned char *) viff_info.comment); 292 viff_info.comment[511]='\0'; 293 if (strlen(viff_info.comment) > 4) 294 (void) SetImageProperty(image,"comment",viff_info.comment,exception); 295 if ((viff_info.machine_dependency == VFF_DEP_DECORDER) || 296 (viff_info.machine_dependency == VFF_DEP_NSORDER)) 297 image->endian=LSBEndian; 298 else 299 image->endian=MSBEndian; 300 viff_info.rows=ReadBlobLong(image); 301 viff_info.columns=ReadBlobLong(image); 302 viff_info.subrows=ReadBlobLong(image); 303 viff_info.x_offset=(int) ReadBlobLong(image); 304 viff_info.y_offset=(int) ReadBlobLong(image); 305 viff_info.x_bits_per_pixel=(float) ReadBlobLong(image); 306 viff_info.y_bits_per_pixel=(float) ReadBlobLong(image); 307 viff_info.location_type=ReadBlobLong(image); 308 viff_info.location_dimension=ReadBlobLong(image); 309 viff_info.number_of_images=ReadBlobLong(image); 310 viff_info.number_data_bands=ReadBlobLong(image); 311 viff_info.data_storage_type=ReadBlobLong(image); 312 viff_info.data_encode_scheme=ReadBlobLong(image); 313 viff_info.map_scheme=ReadBlobLong(image); 314 viff_info.map_storage_type=ReadBlobLong(image); 315 viff_info.map_rows=ReadBlobLong(image); 316 viff_info.map_columns=ReadBlobLong(image); 317 viff_info.map_subrows=ReadBlobLong(image); 318 viff_info.map_enable=ReadBlobLong(image); 319 viff_info.maps_per_cycle=ReadBlobLong(image); 320 viff_info.color_space_model=ReadBlobLong(image); 321 for (i=0; i < 420; i++) 322 (void) ReadBlobByte(image); 323 image->columns=viff_info.rows; 324 image->rows=viff_info.columns; 325 image->depth=viff_info.x_bits_per_pixel <= 8 ? 8UL : 326 MAGICKCORE_QUANTUM_DEPTH; 327 /* 328 Verify that we can read this VIFF image. 329 */ 330 number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows; 331 if (number_pixels != (size_t) number_pixels) 332 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 333 if (number_pixels == 0) 334 ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported"); 335 if ((viff_info.number_data_bands < 1) || (viff_info.number_data_bands > 4)) 336 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 337 if ((viff_info.data_storage_type != VFF_TYP_BIT) && 338 (viff_info.data_storage_type != VFF_TYP_1_BYTE) && 339 (viff_info.data_storage_type != VFF_TYP_2_BYTE) && 340 (viff_info.data_storage_type != VFF_TYP_4_BYTE) && 341 (viff_info.data_storage_type != VFF_TYP_FLOAT) && 342 (viff_info.data_storage_type != VFF_TYP_DOUBLE)) 343 ThrowReaderException(CoderError,"DataStorageTypeIsNotSupported"); 344 if (viff_info.data_encode_scheme != VFF_DES_RAW) 345 ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported"); 346 if ((viff_info.map_storage_type != VFF_MAPTYP_NONE) && 347 (viff_info.map_storage_type != VFF_MAPTYP_1_BYTE) && 348 (viff_info.map_storage_type != VFF_MAPTYP_2_BYTE) && 349 (viff_info.map_storage_type != VFF_MAPTYP_4_BYTE) && 350 (viff_info.map_storage_type != VFF_MAPTYP_FLOAT) && 351 (viff_info.map_storage_type != VFF_MAPTYP_DOUBLE)) 352 ThrowReaderException(CoderError,"MapStorageTypeIsNotSupported"); 353 if ((viff_info.color_space_model != VFF_CM_NONE) && 354 (viff_info.color_space_model != VFF_CM_ntscRGB) && 355 (viff_info.color_space_model != VFF_CM_genericRGB)) 356 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported"); 357 if (viff_info.location_type != VFF_LOC_IMPLICIT) 358 ThrowReaderException(CoderError,"LocationTypeIsNotSupported"); 359 if (viff_info.number_of_images != 1) 360 ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported"); 361 if (viff_info.map_rows == 0) 362 viff_info.map_scheme=VFF_MS_NONE; 363 switch ((int) viff_info.map_scheme) 364 { 365 case VFF_MS_NONE: 366 { 367 if (viff_info.number_data_bands < 3) 368 { 369 /* 370 Create linear color ramp. 371 */ 372 if (viff_info.data_storage_type == VFF_TYP_BIT) 373 image->colors=2; 374 else 375 if (viff_info.data_storage_type == VFF_MAPTYP_1_BYTE) 376 image->colors=256UL; 377 else 378 image->colors=image->depth <= 8 ? 256UL : 65536UL; 379 status=AcquireImageColormap(image,image->colors,exception); 380 if (status == MagickFalse) 381 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 382 } 383 break; 384 } 385 case VFF_MS_ONEPERBAND: 386 case VFF_MS_SHARED: 387 { 388 unsigned char 389 *viff_colormap; 390 391 /* 392 Allocate VIFF colormap. 393 */ 394 switch ((int) viff_info.map_storage_type) 395 { 396 case VFF_MAPTYP_1_BYTE: bytes_per_pixel=1; break; 397 case VFF_MAPTYP_2_BYTE: bytes_per_pixel=2; break; 398 case VFF_MAPTYP_4_BYTE: bytes_per_pixel=4; break; 399 case VFF_MAPTYP_FLOAT: bytes_per_pixel=4; break; 400 case VFF_MAPTYP_DOUBLE: bytes_per_pixel=8; break; 401 default: bytes_per_pixel=1; break; 402 } 403 image->colors=viff_info.map_columns; 404 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 405 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 406 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 407 viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap)); 408 if (viff_colormap == (unsigned char *) NULL) 409 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 410 /* 411 Read VIFF raster colormap. 412 */ 413 count=ReadBlob(image,bytes_per_pixel*image->colors*viff_info.map_rows, 414 viff_colormap); 415 lsb_first=1; 416 if (*(char *) &lsb_first && 417 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 418 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 419 switch ((int) viff_info.map_storage_type) 420 { 421 case VFF_MAPTYP_2_BYTE: 422 { 423 MSBOrderShort(viff_colormap,(bytes_per_pixel*image->colors* 424 viff_info.map_rows)); 425 break; 426 } 427 case VFF_MAPTYP_4_BYTE: 428 case VFF_MAPTYP_FLOAT: 429 { 430 MSBOrderLong(viff_colormap,(bytes_per_pixel*image->colors* 431 viff_info.map_rows)); 432 break; 433 } 434 default: break; 435 } 436 for (i=0; i < (ssize_t) (viff_info.map_rows*image->colors); i++) 437 { 438 switch ((int) viff_info.map_storage_type) 439 { 440 case VFF_MAPTYP_2_BYTE: value=1.0*((short *) viff_colormap)[i]; break; 441 case VFF_MAPTYP_4_BYTE: value=1.0*((int *) viff_colormap)[i]; break; 442 case VFF_MAPTYP_FLOAT: value=((float *) viff_colormap)[i]; break; 443 case VFF_MAPTYP_DOUBLE: value=((double *) viff_colormap)[i]; break; 444 default: value=1.0*viff_colormap[i]; break; 445 } 446 if (i < (ssize_t) image->colors) 447 { 448 image->colormap[i].red=ScaleCharToQuantum((unsigned char) value); 449 image->colormap[i].green= 450 ScaleCharToQuantum((unsigned char) value); 451 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) value); 452 } 453 else 454 if (i < (ssize_t) (2*image->colors)) 455 image->colormap[i % image->colors].green= 456 ScaleCharToQuantum((unsigned char) value); 457 else 458 if (i < (ssize_t) (3*image->colors)) 459 image->colormap[i % image->colors].blue= 460 ScaleCharToQuantum((unsigned char) value); 461 } 462 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 463 break; 464 } 465 default: 466 ThrowReaderException(CoderError,"ColormapTypeNotSupported"); 467 } 468 /* 469 Initialize image structure. 470 */ 471 image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait : 472 UndefinedPixelTrait; 473 image->storage_class=(viff_info.number_data_bands < 3 ? PseudoClass : 474 DirectClass); 475 image->columns=viff_info.rows; 476 image->rows=viff_info.columns; 477 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 478 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 479 break; 480 status=SetImageExtent(image,image->columns,image->rows,exception); 481 if (status == MagickFalse) 482 return(DestroyImageList(image)); 483 /* 484 Allocate VIFF pixels. 485 */ 486 switch ((int) viff_info.data_storage_type) 487 { 488 case VFF_TYP_2_BYTE: bytes_per_pixel=2; break; 489 case VFF_TYP_4_BYTE: bytes_per_pixel=4; break; 490 case VFF_TYP_FLOAT: bytes_per_pixel=4; break; 491 case VFF_TYP_DOUBLE: bytes_per_pixel=8; break; 492 default: bytes_per_pixel=1; break; 493 } 494 if (viff_info.data_storage_type == VFF_TYP_BIT) 495 max_packets=((image->columns+7UL) >> 3UL)*image->rows; 496 else 497 max_packets=(size_t) (number_pixels*viff_info.number_data_bands); 498 pixels=(unsigned char *) AcquireQuantumMemory(max_packets, 499 bytes_per_pixel*sizeof(*pixels)); 500 if (pixels == (unsigned char *) NULL) 501 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 502 count=ReadBlob(image,bytes_per_pixel*max_packets,pixels); 503 lsb_first=1; 504 if (*(char *) &lsb_first && 505 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 506 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 507 switch ((int) viff_info.data_storage_type) 508 { 509 case VFF_TYP_2_BYTE: 510 { 511 MSBOrderShort(pixels,bytes_per_pixel*max_packets); 512 break; 513 } 514 case VFF_TYP_4_BYTE: 515 case VFF_TYP_FLOAT: 516 { 517 MSBOrderLong(pixels,bytes_per_pixel*max_packets); 518 break; 519 } 520 default: break; 521 } 522 min_value=0.0; 523 scale_factor=1.0; 524 if ((viff_info.data_storage_type != VFF_TYP_1_BYTE) && 525 (viff_info.map_scheme == VFF_MS_NONE)) 526 { 527 double 528 max_value; 529 530 /* 531 Determine scale factor. 532 */ 533 switch ((int) viff_info.data_storage_type) 534 { 535 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[0]; break; 536 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[0]; break; 537 case VFF_TYP_FLOAT: value=((float *) pixels)[0]; break; 538 case VFF_TYP_DOUBLE: value=((double *) pixels)[0]; break; 539 default: value=1.0*pixels[0]; break; 540 } 541 max_value=value; 542 min_value=value; 543 for (i=0; i < (ssize_t) max_packets; i++) 544 { 545 switch ((int) viff_info.data_storage_type) 546 { 547 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break; 548 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break; 549 case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break; 550 case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break; 551 default: value=1.0*pixels[i]; break; 552 } 553 if (value > max_value) 554 max_value=value; 555 else 556 if (value < min_value) 557 min_value=value; 558 } 559 if ((min_value == 0) && (max_value == 0)) 560 scale_factor=0; 561 else 562 if (min_value == max_value) 563 { 564 scale_factor=(double) QuantumRange/min_value; 565 min_value=0; 566 } 567 else 568 scale_factor=(double) QuantumRange/(max_value-min_value); 569 } 570 /* 571 Convert pixels to Quantum size. 572 */ 573 p=(unsigned char *) pixels; 574 for (i=0; i < (ssize_t) max_packets; i++) 575 { 576 switch ((int) viff_info.data_storage_type) 577 { 578 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break; 579 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break; 580 case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break; 581 case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break; 582 default: value=1.0*pixels[i]; break; 583 } 584 if (viff_info.map_scheme == VFF_MS_NONE) 585 { 586 value=(value-min_value)*scale_factor; 587 if (value > QuantumRange) 588 value=QuantumRange; 589 else 590 if (value < 0) 591 value=0; 592 } 593 *p=(unsigned char) value; 594 p++; 595 } 596 /* 597 Convert VIFF raster image to pixel packets. 598 */ 599 p=(unsigned char *) pixels; 600 if (viff_info.data_storage_type == VFF_TYP_BIT) 601 { 602 /* 603 Convert bitmap scanline. 604 */ 605 for (y=0; y < (ssize_t) image->rows; y++) 606 { 607 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 608 if (q == (Quantum *) NULL) 609 break; 610 for (x=0; x < (ssize_t) (image->columns-7); x+=8) 611 { 612 for (bit=0; bit < 8; bit++) 613 { 614 quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1); 615 SetPixelIndex(image,quantum,q); 616 q+=GetPixelChannels(image); 617 } 618 p++; 619 } 620 if ((image->columns % 8) != 0) 621 { 622 for (bit=0; bit < (int) (image->columns % 8); bit++) 623 { 624 quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1); 625 SetPixelIndex(image,quantum,q); 626 q+=GetPixelChannels(image); 627 } 628 p++; 629 } 630 if (SyncAuthenticPixels(image,exception) == MagickFalse) 631 break; 632 if (image->previous == (Image *) NULL) 633 { 634 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 635 image->rows); 636 if (status == MagickFalse) 637 break; 638 } 639 } 640 } 641 else 642 if (image->storage_class == PseudoClass) 643 for (y=0; y < (ssize_t) image->rows; y++) 644 { 645 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 646 if (q == (Quantum *) NULL) 647 break; 648 for (x=0; x < (ssize_t) image->columns; x++) 649 { 650 SetPixelIndex(image,*p++,q); 651 q+=GetPixelChannels(image); 652 } 653 if (SyncAuthenticPixels(image,exception) == MagickFalse) 654 break; 655 if (image->previous == (Image *) NULL) 656 { 657 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 658 image->rows); 659 if (status == MagickFalse) 660 break; 661 } 662 } 663 else 664 { 665 /* 666 Convert DirectColor scanline. 667 */ 668 number_pixels=(MagickSizeType) image->columns*image->rows; 669 for (y=0; y < (ssize_t) image->rows; y++) 670 { 671 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 672 if (q == (Quantum *) NULL) 673 break; 674 for (x=0; x < (ssize_t) image->columns; x++) 675 { 676 SetPixelRed(image,ScaleCharToQuantum(*p),q); 677 SetPixelGreen(image,ScaleCharToQuantum(*(p+number_pixels)),q); 678 SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q); 679 if (image->colors != 0) 680 { 681 ssize_t 682 index; 683 684 index=(ssize_t) GetPixelRed(image,q); 685 SetPixelRed(image,image->colormap[ 686 ConstrainColormapIndex(image,index,exception)].red,q); 687 index=(ssize_t) GetPixelGreen(image,q); 688 SetPixelGreen(image,image->colormap[ 689 ConstrainColormapIndex(image,index,exception)].green,q); 690 index=(ssize_t) GetPixelBlue(image,q); 691 SetPixelBlue(image,image->colormap[ 692 ConstrainColormapIndex(image,index,exception)].blue,q); 693 } 694 SetPixelAlpha(image,image->alpha_trait == BlendPixelTrait ? 695 ScaleCharToQuantum(*(p+number_pixels*3)) : OpaqueAlpha,q); 696 p++; 697 q+=GetPixelChannels(image); 698 } 699 if (SyncAuthenticPixels(image,exception) == MagickFalse) 700 break; 701 if (image->previous == (Image *) NULL) 702 { 703 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 704 image->rows); 705 if (status == MagickFalse) 706 break; 707 } 708 } 709 } 710 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 711 if (image->storage_class == PseudoClass) 712 (void) SyncImage(image,exception); 713 if (EOFBlob(image) != MagickFalse) 714 { 715 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 716 image->filename); 717 break; 718 } 719 /* 720 Proceed to next image. 721 */ 722 if (image_info->number_scenes != 0) 723 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 724 break; 725 count=ReadBlob(image,1,&viff_info.identifier); 726 if ((count != 0) && (viff_info.identifier == 0xab)) 727 { 728 /* 729 Allocate next image structure. 730 */ 731 AcquireNextImage(image_info,image,exception); 732 if (GetNextImageInList(image) == (Image *) NULL) 733 { 734 image=DestroyImageList(image); 735 return((Image *) NULL); 736 } 737 image=SyncNextImageInList(image); 738 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 739 GetBlobSize(image)); 740 if (status == MagickFalse) 741 break; 742 } 743 } while ((count != 0) && (viff_info.identifier == 0xab)); 744 (void) CloseBlob(image); 745 return(GetFirstImageInList(image)); 746} 747 748/* 749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 750% % 751% % 752% % 753% R e g i s t e r V I F F I m a g e % 754% % 755% % 756% % 757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 758% 759% RegisterVIFFImage() adds properties for the VIFF image format to 760% the list of supported formats. The properties include the image format 761% tag, a method to read and/or write the format, whether the format 762% supports the saving of more than one frame to the same file or blob, 763% whether the format supports native in-memory I/O, and a brief 764% description of the format. 765% 766% The format of the RegisterVIFFImage method is: 767% 768% size_t RegisterVIFFImage(void) 769% 770*/ 771ModuleExport size_t RegisterVIFFImage(void) 772{ 773 MagickInfo 774 *entry; 775 776 entry=SetMagickInfo("VIFF"); 777 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 778 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 779 entry->magick=(IsImageFormatHandler *) IsVIFF; 780 entry->description=ConstantString("Khoros Visualization image"); 781 entry->module=ConstantString("VIFF"); 782 (void) RegisterMagickInfo(entry); 783 entry=SetMagickInfo("XV"); 784 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 785 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 786 entry->description=ConstantString("Khoros Visualization image"); 787 entry->module=ConstantString("VIFF"); 788 (void) RegisterMagickInfo(entry); 789 return(MagickImageCoderSignature); 790} 791 792/* 793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 794% % 795% % 796% % 797% U n r e g i s t e r V I F F I m a g e % 798% % 799% % 800% % 801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 802% 803% UnregisterVIFFImage() removes format registrations made by the 804% VIFF module from the list of supported formats. 805% 806% The format of the UnregisterVIFFImage method is: 807% 808% UnregisterVIFFImage(void) 809% 810*/ 811ModuleExport void UnregisterVIFFImage(void) 812{ 813 (void) UnregisterMagickInfo("VIFF"); 814 (void) UnregisterMagickInfo("XV"); 815} 816 817/* 818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 819% % 820% % 821% % 822% W r i t e V I F F I m a g e % 823% % 824% % 825% % 826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 827% 828% WriteVIFFImage() writes an image to a file in the VIFF image format. 829% 830% The format of the WriteVIFFImage method is: 831% 832% MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 833% Image *image,ExceptionInfo *exception) 834% 835% A description of each parameter follows. 836% 837% o image_info: the image info. 838% 839% o image: The image. 840% 841% o exception: return any errors or warnings in this structure. 842% 843*/ 844 845static inline size_t MagickMin(const size_t x,const size_t y) 846{ 847 if (x < y) 848 return(x); 849 return(y); 850} 851 852static MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 853 Image *image,ExceptionInfo *exception) 854{ 855#define VFF_CM_genericRGB 15 856#define VFF_CM_NONE 0 857#define VFF_DEP_IEEEORDER 0x2 858#define VFF_DES_RAW 0 859#define VFF_LOC_IMPLICIT 1 860#define VFF_MAPTYP_NONE 0 861#define VFF_MAPTYP_1_BYTE 1 862#define VFF_MS_NONE 0 863#define VFF_MS_ONEPERBAND 1 864#define VFF_TYP_BIT 0 865#define VFF_TYP_1_BYTE 1 866 867 typedef struct _ViffInfo 868 { 869 char 870 identifier, 871 file_type, 872 release, 873 version, 874 machine_dependency, 875 reserve[3], 876 comment[512]; 877 878 size_t 879 rows, 880 columns, 881 subrows; 882 883 int 884 x_offset, 885 y_offset; 886 887 unsigned int 888 x_bits_per_pixel, 889 y_bits_per_pixel, 890 location_type, 891 location_dimension, 892 number_of_images, 893 number_data_bands, 894 data_storage_type, 895 data_encode_scheme, 896 map_scheme, 897 map_storage_type, 898 map_rows, 899 map_columns, 900 map_subrows, 901 map_enable, 902 maps_per_cycle, 903 color_space_model; 904 } ViffInfo; 905 906 const char 907 *value; 908 909 MagickBooleanType 910 status; 911 912 MagickOffsetType 913 scene; 914 915 MagickSizeType 916 number_pixels, 917 packets; 918 919 MemoryInfo 920 *pixel_info; 921 922 register const Quantum 923 *p; 924 925 register ssize_t 926 x; 927 928 register ssize_t 929 i; 930 931 register unsigned char 932 *q; 933 934 ssize_t 935 y; 936 937 unsigned char 938 *pixels; 939 940 ViffInfo 941 viff_info; 942 943 /* 944 Open output image file. 945 */ 946 assert(image_info != (const ImageInfo *) NULL); 947 assert(image_info->signature == MagickSignature); 948 assert(image != (Image *) NULL); 949 assert(image->signature == MagickSignature); 950 if (image->debug != MagickFalse) 951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 952 assert(exception != (ExceptionInfo *) NULL); 953 assert(exception->signature == MagickSignature); 954 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 955 if (status == MagickFalse) 956 return(status); 957 (void) ResetMagickMemory(&viff_info,0,sizeof(ViffInfo)); 958 scene=0; 959 do 960 { 961 /* 962 Initialize VIFF image structure. 963 */ 964 (void) TransformImageColorspace(image,sRGBColorspace,exception); 965DisableMSCWarning(4310) 966 viff_info.identifier=(char) 0xab; 967RestoreMSCWarning 968 viff_info.file_type=1; 969 viff_info.release=1; 970 viff_info.version=3; 971 viff_info.machine_dependency=VFF_DEP_IEEEORDER; /* IEEE byte ordering */ 972 *viff_info.comment='\0'; 973 value=GetImageProperty(image,"comment",exception); 974 if (value != (const char *) NULL) 975 (void) CopyMagickString(viff_info.comment,value,MagickMin(strlen(value), 976 511)+1); 977 viff_info.rows=image->columns; 978 viff_info.columns=image->rows; 979 viff_info.subrows=0; 980 viff_info.x_offset=(~0); 981 viff_info.y_offset=(~0); 982 viff_info.x_bits_per_pixel=0; 983 viff_info.y_bits_per_pixel=0; 984 viff_info.location_type=VFF_LOC_IMPLICIT; 985 viff_info.location_dimension=0; 986 viff_info.number_of_images=1; 987 viff_info.data_encode_scheme=VFF_DES_RAW; 988 viff_info.map_scheme=VFF_MS_NONE; 989 viff_info.map_storage_type=VFF_MAPTYP_NONE; 990 viff_info.map_rows=0; 991 viff_info.map_columns=0; 992 viff_info.map_subrows=0; 993 viff_info.map_enable=1; /* no colormap */ 994 viff_info.maps_per_cycle=0; 995 number_pixels=(MagickSizeType) image->columns*image->rows; 996 if (image->storage_class == DirectClass) 997 { 998 /* 999 Full color VIFF raster. 1000 */ 1001 viff_info.number_data_bands=image->alpha_trait ? 4U : 3U; 1002 viff_info.color_space_model=VFF_CM_genericRGB; 1003 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1004 packets=viff_info.number_data_bands*number_pixels; 1005 } 1006 else 1007 { 1008 viff_info.number_data_bands=1; 1009 viff_info.color_space_model=VFF_CM_NONE; 1010 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1011 packets=number_pixels; 1012 if (IsImageGray(image,exception) == MagickFalse) 1013 { 1014 /* 1015 Colormapped VIFF raster. 1016 */ 1017 viff_info.map_scheme=VFF_MS_ONEPERBAND; 1018 viff_info.map_storage_type=VFF_MAPTYP_1_BYTE; 1019 viff_info.map_rows=3; 1020 viff_info.map_columns=(unsigned int) image->colors; 1021 } 1022 else 1023 if (image->colors <= 2) 1024 { 1025 /* 1026 Monochrome VIFF raster. 1027 */ 1028 viff_info.data_storage_type=VFF_TYP_BIT; 1029 packets=((image->columns+7) >> 3)*image->rows; 1030 } 1031 } 1032 /* 1033 Write VIFF image header (pad to 1024 bytes). 1034 */ 1035 (void) WriteBlob(image,sizeof(viff_info.identifier),(unsigned char *) 1036 &viff_info.identifier); 1037 (void) WriteBlob(image,sizeof(viff_info.file_type),(unsigned char *) 1038 &viff_info.file_type); 1039 (void) WriteBlob(image,sizeof(viff_info.release),(unsigned char *) 1040 &viff_info.release); 1041 (void) WriteBlob(image,sizeof(viff_info.version),(unsigned char *) 1042 &viff_info.version); 1043 (void) WriteBlob(image,sizeof(viff_info.machine_dependency), 1044 (unsigned char *) &viff_info.machine_dependency); 1045 (void) WriteBlob(image,sizeof(viff_info.reserve),(unsigned char *) 1046 viff_info.reserve); 1047 (void) WriteBlob(image,512,(unsigned char *) viff_info.comment); 1048 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.rows); 1049 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.columns); 1050 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.subrows); 1051 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_offset); 1052 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_offset); 1053 viff_info.x_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16)); 1054 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_bits_per_pixel); 1055 viff_info.y_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16)); 1056 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_bits_per_pixel); 1057 (void) WriteBlobMSBLong(image,viff_info.location_type); 1058 (void) WriteBlobMSBLong(image,viff_info.location_dimension); 1059 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_of_images); 1060 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_data_bands); 1061 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_storage_type); 1062 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_encode_scheme); 1063 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_scheme); 1064 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_storage_type); 1065 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_rows); 1066 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_columns); 1067 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_subrows); 1068 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable); 1069 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle); 1070 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model); 1071 for (i=0; i < 420; i++) 1072 (void) WriteBlobByte(image,'\0'); 1073 /* 1074 Convert MIFF to VIFF raster pixels. 1075 */ 1076 pixel_info=AcquireVirtualMemory((size_t) packets,sizeof(*pixels)); 1077 if (pixel_info == (MemoryInfo *) NULL) 1078 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1079 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1080 q=pixels; 1081 if (image->storage_class == DirectClass) 1082 { 1083 /* 1084 Convert DirectClass packet to VIFF RGB pixel. 1085 */ 1086 number_pixels=(MagickSizeType) image->columns*image->rows; 1087 for (y=0; y < (ssize_t) image->rows; y++) 1088 { 1089 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1090 if (p == (const Quantum *) NULL) 1091 break; 1092 for (x=0; x < (ssize_t) image->columns; x++) 1093 { 1094 *q=ScaleQuantumToChar(GetPixelRed(image,p)); 1095 *(q+number_pixels)=ScaleQuantumToChar(GetPixelGreen(image,p)); 1096 *(q+number_pixels*2)=ScaleQuantumToChar(GetPixelBlue(image,p)); 1097 if (image->alpha_trait == BlendPixelTrait) 1098 *(q+number_pixels*3)=ScaleQuantumToChar((Quantum) 1099 (GetPixelAlpha(image,p))); 1100 p+=GetPixelChannels(image); 1101 q++; 1102 } 1103 if (image->previous == (Image *) NULL) 1104 { 1105 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1106 image->rows); 1107 if (status == MagickFalse) 1108 break; 1109 } 1110 } 1111 } 1112 else 1113 if (IsImageGray(image,exception) == MagickFalse) 1114 { 1115 unsigned char 1116 *viff_colormap; 1117 1118 /* 1119 Dump colormap to file. 1120 */ 1121 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 1122 3*sizeof(*viff_colormap)); 1123 if (viff_colormap == (unsigned char *) NULL) 1124 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1125 q=viff_colormap; 1126 for (i=0; i < (ssize_t) image->colors; i++) 1127 *q++=ScaleQuantumToChar(image->colormap[i].red); 1128 for (i=0; i < (ssize_t) image->colors; i++) 1129 *q++=ScaleQuantumToChar(image->colormap[i].green); 1130 for (i=0; i < (ssize_t) image->colors; i++) 1131 *q++=ScaleQuantumToChar(image->colormap[i].blue); 1132 (void) WriteBlob(image,3*image->colors,viff_colormap); 1133 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 1134 /* 1135 Convert PseudoClass packet to VIFF colormapped pixels. 1136 */ 1137 q=pixels; 1138 for (y=0; y < (ssize_t) image->rows; y++) 1139 { 1140 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1141 if (p == (const Quantum *) NULL) 1142 break; 1143 for (x=0; x < (ssize_t) image->columns; x++) 1144 { 1145 *q++=(unsigned char) GetPixelIndex(image,p); 1146 p+=GetPixelChannels(image); 1147 } 1148 if (image->previous == (Image *) NULL) 1149 { 1150 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1151 image->rows); 1152 if (status == MagickFalse) 1153 break; 1154 } 1155 } 1156 } 1157 else 1158 if (image->colors <= 2) 1159 { 1160 ssize_t 1161 x, 1162 y; 1163 1164 register unsigned char 1165 bit, 1166 byte; 1167 1168 /* 1169 Convert PseudoClass image to a VIFF monochrome image. 1170 */ 1171 (void) SetImageType(image,BilevelType,exception); 1172 for (y=0; y < (ssize_t) image->rows; y++) 1173 { 1174 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1175 if (p == (const Quantum *) NULL) 1176 break; 1177 bit=0; 1178 byte=0; 1179 for (x=0; x < (ssize_t) image->columns; x++) 1180 { 1181 byte>>=1; 1182 if (GetPixelLuma(image,p) < (QuantumRange/2.0)) 1183 byte|=0x80; 1184 bit++; 1185 if (bit == 8) 1186 { 1187 *q++=byte; 1188 bit=0; 1189 byte=0; 1190 } 1191 p+=GetPixelChannels(image); 1192 } 1193 if (bit != 0) 1194 *q++=byte >> (8-bit); 1195 if (image->previous == (Image *) NULL) 1196 { 1197 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1198 y,image->rows); 1199 if (status == MagickFalse) 1200 break; 1201 } 1202 } 1203 } 1204 else 1205 { 1206 /* 1207 Convert PseudoClass packet to VIFF grayscale pixel. 1208 */ 1209 for (y=0; y < (ssize_t) image->rows; y++) 1210 { 1211 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1212 if (p == (const Quantum *) NULL) 1213 break; 1214 for (x=0; x < (ssize_t) image->columns; x++) 1215 { 1216 *q++=(unsigned char) ClampToQuantum(GetPixelLuma(image,p)); 1217 p+=GetPixelChannels(image); 1218 } 1219 if (image->previous == (Image *) NULL) 1220 { 1221 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1222 y,image->rows); 1223 if (status == MagickFalse) 1224 break; 1225 } 1226 } 1227 } 1228 (void) WriteBlob(image,(size_t) packets,pixels); 1229 pixel_info=RelinquishVirtualMemory(pixel_info); 1230 if (GetNextImageInList(image) == (Image *) NULL) 1231 break; 1232 image=SyncNextImageInList(image); 1233 status=SetImageProgress(image,SaveImagesTag,scene++, 1234 GetImageListLength(image)); 1235 if (status == MagickFalse) 1236 break; 1237 } while (image_info->adjoin != MagickFalse); 1238 (void) CloseBlob(image); 1239 return(MagickTrue); 1240} 1241