viff.c revision 06b627a07ff44e1ff93ef1288c9f428066ded10d
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 != 1) || ((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 if (EOFBlob(image) != MagickFalse) 324 ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); 325 image->columns=viff_info.rows; 326 image->rows=viff_info.columns; 327 image->depth=viff_info.x_bits_per_pixel <= 8 ? 8UL : 328 MAGICKCORE_QUANTUM_DEPTH; 329 /* 330 Verify that we can read this VIFF image. 331 */ 332 number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows; 333 if (number_pixels != (size_t) number_pixels) 334 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 335 if (number_pixels == 0) 336 ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported"); 337 if ((viff_info.number_data_bands < 1) || (viff_info.number_data_bands > 4)) 338 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 339 if ((viff_info.data_storage_type != VFF_TYP_BIT) && 340 (viff_info.data_storage_type != VFF_TYP_1_BYTE) && 341 (viff_info.data_storage_type != VFF_TYP_2_BYTE) && 342 (viff_info.data_storage_type != VFF_TYP_4_BYTE) && 343 (viff_info.data_storage_type != VFF_TYP_FLOAT) && 344 (viff_info.data_storage_type != VFF_TYP_DOUBLE)) 345 ThrowReaderException(CoderError,"DataStorageTypeIsNotSupported"); 346 if (viff_info.data_encode_scheme != VFF_DES_RAW) 347 ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported"); 348 if ((viff_info.map_storage_type != VFF_MAPTYP_NONE) && 349 (viff_info.map_storage_type != VFF_MAPTYP_1_BYTE) && 350 (viff_info.map_storage_type != VFF_MAPTYP_2_BYTE) && 351 (viff_info.map_storage_type != VFF_MAPTYP_4_BYTE) && 352 (viff_info.map_storage_type != VFF_MAPTYP_FLOAT) && 353 (viff_info.map_storage_type != VFF_MAPTYP_DOUBLE)) 354 ThrowReaderException(CoderError,"MapStorageTypeIsNotSupported"); 355 if ((viff_info.color_space_model != VFF_CM_NONE) && 356 (viff_info.color_space_model != VFF_CM_ntscRGB) && 357 (viff_info.color_space_model != VFF_CM_genericRGB)) 358 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported"); 359 if (viff_info.location_type != VFF_LOC_IMPLICIT) 360 ThrowReaderException(CoderError,"LocationTypeIsNotSupported"); 361 if (viff_info.number_of_images != 1) 362 ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported"); 363 if (viff_info.map_rows == 0) 364 viff_info.map_scheme=VFF_MS_NONE; 365 switch ((int) viff_info.map_scheme) 366 { 367 case VFF_MS_NONE: 368 { 369 if (viff_info.number_data_bands < 3) 370 { 371 /* 372 Create linear color ramp. 373 */ 374 if (viff_info.data_storage_type == VFF_TYP_BIT) 375 image->colors=2; 376 else 377 if (viff_info.data_storage_type == VFF_MAPTYP_1_BYTE) 378 image->colors=256UL; 379 else 380 image->colors=image->depth <= 8 ? 256UL : 65536UL; 381 status=AcquireImageColormap(image,image->colors,exception); 382 if (status == MagickFalse) 383 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 384 } 385 break; 386 } 387 case VFF_MS_ONEPERBAND: 388 case VFF_MS_SHARED: 389 { 390 unsigned char 391 *viff_colormap; 392 393 /* 394 Allocate VIFF colormap. 395 */ 396 switch ((int) viff_info.map_storage_type) 397 { 398 case VFF_MAPTYP_1_BYTE: bytes_per_pixel=1; break; 399 case VFF_MAPTYP_2_BYTE: bytes_per_pixel=2; break; 400 case VFF_MAPTYP_4_BYTE: bytes_per_pixel=4; break; 401 case VFF_MAPTYP_FLOAT: bytes_per_pixel=4; break; 402 case VFF_MAPTYP_DOUBLE: bytes_per_pixel=8; break; 403 default: bytes_per_pixel=1; break; 404 } 405 image->colors=viff_info.map_columns; 406 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 407 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 408 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 409 viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap)); 410 if (viff_colormap == (unsigned char *) NULL) 411 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 412 /* 413 Read VIFF raster colormap. 414 */ 415 count=ReadBlob(image,bytes_per_pixel*image->colors*viff_info.map_rows, 416 viff_colormap); 417 lsb_first=1; 418 if (*(char *) &lsb_first && 419 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 420 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 421 switch ((int) viff_info.map_storage_type) 422 { 423 case VFF_MAPTYP_2_BYTE: 424 { 425 MSBOrderShort(viff_colormap,(bytes_per_pixel*image->colors* 426 viff_info.map_rows)); 427 break; 428 } 429 case VFF_MAPTYP_4_BYTE: 430 case VFF_MAPTYP_FLOAT: 431 { 432 MSBOrderLong(viff_colormap,(bytes_per_pixel*image->colors* 433 viff_info.map_rows)); 434 break; 435 } 436 default: break; 437 } 438 for (i=0; i < (ssize_t) (viff_info.map_rows*image->colors); i++) 439 { 440 switch ((int) viff_info.map_storage_type) 441 { 442 case VFF_MAPTYP_2_BYTE: value=1.0*((short *) viff_colormap)[i]; break; 443 case VFF_MAPTYP_4_BYTE: value=1.0*((int *) viff_colormap)[i]; break; 444 case VFF_MAPTYP_FLOAT: value=((float *) viff_colormap)[i]; break; 445 case VFF_MAPTYP_DOUBLE: value=((double *) viff_colormap)[i]; break; 446 default: value=1.0*viff_colormap[i]; break; 447 } 448 if (i < (ssize_t) image->colors) 449 { 450 image->colormap[i].red=ScaleCharToQuantum((unsigned char) value); 451 image->colormap[i].green= 452 ScaleCharToQuantum((unsigned char) value); 453 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) value); 454 } 455 else 456 if (i < (ssize_t) (2*image->colors)) 457 image->colormap[i % image->colors].green= 458 ScaleCharToQuantum((unsigned char) value); 459 else 460 if (i < (ssize_t) (3*image->colors)) 461 image->colormap[i % image->colors].blue= 462 ScaleCharToQuantum((unsigned char) value); 463 } 464 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 465 break; 466 } 467 default: 468 ThrowReaderException(CoderError,"ColormapTypeNotSupported"); 469 } 470 /* 471 Initialize image structure. 472 */ 473 image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait : 474 UndefinedPixelTrait; 475 image->storage_class=(viff_info.number_data_bands < 3 ? PseudoClass : 476 DirectClass); 477 image->columns=viff_info.rows; 478 image->rows=viff_info.columns; 479 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 480 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 481 break; 482 status=SetImageExtent(image,image->columns,image->rows,exception); 483 if (status == MagickFalse) 484 return(DestroyImageList(image)); 485 /* 486 Allocate VIFF pixels. 487 */ 488 switch ((int) viff_info.data_storage_type) 489 { 490 case VFF_TYP_2_BYTE: bytes_per_pixel=2; break; 491 case VFF_TYP_4_BYTE: bytes_per_pixel=4; break; 492 case VFF_TYP_FLOAT: bytes_per_pixel=4; break; 493 case VFF_TYP_DOUBLE: bytes_per_pixel=8; break; 494 default: bytes_per_pixel=1; break; 495 } 496 if (viff_info.data_storage_type == VFF_TYP_BIT) 497 max_packets=((image->columns+7UL) >> 3UL)*image->rows; 498 else 499 max_packets=(size_t) (number_pixels*viff_info.number_data_bands); 500 pixels=(unsigned char *) AcquireQuantumMemory(max_packets, 501 bytes_per_pixel*sizeof(*pixels)); 502 if (pixels == (unsigned char *) NULL) 503 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 504 count=ReadBlob(image,bytes_per_pixel*max_packets,pixels); 505 lsb_first=1; 506 if (*(char *) &lsb_first && 507 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 508 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 509 switch ((int) viff_info.data_storage_type) 510 { 511 case VFF_TYP_2_BYTE: 512 { 513 MSBOrderShort(pixels,bytes_per_pixel*max_packets); 514 break; 515 } 516 case VFF_TYP_4_BYTE: 517 case VFF_TYP_FLOAT: 518 { 519 MSBOrderLong(pixels,bytes_per_pixel*max_packets); 520 break; 521 } 522 default: break; 523 } 524 min_value=0.0; 525 scale_factor=1.0; 526 if ((viff_info.data_storage_type != VFF_TYP_1_BYTE) && 527 (viff_info.map_scheme == VFF_MS_NONE)) 528 { 529 double 530 max_value; 531 532 /* 533 Determine scale factor. 534 */ 535 switch ((int) viff_info.data_storage_type) 536 { 537 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[0]; break; 538 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[0]; break; 539 case VFF_TYP_FLOAT: value=((float *) pixels)[0]; break; 540 case VFF_TYP_DOUBLE: value=((double *) pixels)[0]; break; 541 default: value=1.0*pixels[0]; break; 542 } 543 max_value=value; 544 min_value=value; 545 for (i=0; i < (ssize_t) max_packets; i++) 546 { 547 switch ((int) viff_info.data_storage_type) 548 { 549 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break; 550 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break; 551 case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break; 552 case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break; 553 default: value=1.0*pixels[i]; break; 554 } 555 if (value > max_value) 556 max_value=value; 557 else 558 if (value < min_value) 559 min_value=value; 560 } 561 if ((min_value == 0) && (max_value == 0)) 562 scale_factor=0; 563 else 564 if (min_value == max_value) 565 { 566 scale_factor=(double) QuantumRange/min_value; 567 min_value=0; 568 } 569 else 570 scale_factor=(double) QuantumRange/(max_value-min_value); 571 } 572 /* 573 Convert pixels to Quantum size. 574 */ 575 p=(unsigned char *) pixels; 576 for (i=0; i < (ssize_t) max_packets; i++) 577 { 578 switch ((int) viff_info.data_storage_type) 579 { 580 case VFF_TYP_2_BYTE: value=1.0*((short *) pixels)[i]; break; 581 case VFF_TYP_4_BYTE: value=1.0*((int *) pixels)[i]; break; 582 case VFF_TYP_FLOAT: value=((float *) pixels)[i]; break; 583 case VFF_TYP_DOUBLE: value=((double *) pixels)[i]; break; 584 default: value=1.0*pixels[i]; break; 585 } 586 if (viff_info.map_scheme == VFF_MS_NONE) 587 { 588 value=(value-min_value)*scale_factor; 589 if (value > QuantumRange) 590 value=QuantumRange; 591 else 592 if (value < 0) 593 value=0; 594 } 595 *p=(unsigned char) value; 596 p++; 597 } 598 /* 599 Convert VIFF raster image to pixel packets. 600 */ 601 p=(unsigned char *) pixels; 602 if (viff_info.data_storage_type == VFF_TYP_BIT) 603 { 604 /* 605 Convert bitmap scanline. 606 */ 607 for (y=0; y < (ssize_t) image->rows; y++) 608 { 609 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 610 if (q == (Quantum *) NULL) 611 break; 612 for (x=0; x < (ssize_t) (image->columns-7); x+=8) 613 { 614 for (bit=0; bit < 8; bit++) 615 { 616 quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1); 617 SetPixelRed(image,quantum == 0 ? 0 : QuantumRange,q); 618 SetPixelGreen(image,quantum == 0 ? 0 : QuantumRange,q); 619 SetPixelBlue(image,quantum == 0 ? 0 : QuantumRange,q); 620 if (image->storage_class == PseudoClass) 621 SetPixelIndex(image,quantum,q); 622 q+=GetPixelChannels(image); 623 } 624 p++; 625 } 626 if ((image->columns % 8) != 0) 627 { 628 for (bit=0; bit < (int) (image->columns % 8); bit++) 629 { 630 quantum=(size_t) ((*p) & (0x01 << bit) ? 0 : 1); 631 SetPixelRed(image,quantum == 0 ? 0 : QuantumRange,q); 632 SetPixelGreen(image,quantum == 0 ? 0 : QuantumRange,q); 633 SetPixelBlue(image,quantum == 0 ? 0 : QuantumRange,q); 634 if (image->storage_class == PseudoClass) 635 SetPixelIndex(image,quantum,q); 636 q+=GetPixelChannels(image); 637 } 638 p++; 639 } 640 if (SyncAuthenticPixels(image,exception) == MagickFalse) 641 break; 642 if (image->previous == (Image *) NULL) 643 { 644 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 645 image->rows); 646 if (status == MagickFalse) 647 break; 648 } 649 } 650 } 651 else 652 if (image->storage_class == PseudoClass) 653 for (y=0; y < (ssize_t) image->rows; y++) 654 { 655 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 656 if (q == (Quantum *) NULL) 657 break; 658 for (x=0; x < (ssize_t) image->columns; x++) 659 { 660 SetPixelIndex(image,*p++,q); 661 q+=GetPixelChannels(image); 662 } 663 if (SyncAuthenticPixels(image,exception) == MagickFalse) 664 break; 665 if (image->previous == (Image *) NULL) 666 { 667 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 668 image->rows); 669 if (status == MagickFalse) 670 break; 671 } 672 } 673 else 674 { 675 /* 676 Convert DirectColor scanline. 677 */ 678 number_pixels=(MagickSizeType) image->columns*image->rows; 679 for (y=0; y < (ssize_t) image->rows; y++) 680 { 681 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 682 if (q == (Quantum *) NULL) 683 break; 684 for (x=0; x < (ssize_t) image->columns; x++) 685 { 686 SetPixelRed(image,ScaleCharToQuantum(*p),q); 687 SetPixelGreen(image,ScaleCharToQuantum(*(p+number_pixels)),q); 688 SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q); 689 if (image->colors != 0) 690 { 691 ssize_t 692 index; 693 694 index=(ssize_t) GetPixelRed(image,q); 695 SetPixelRed(image,image->colormap[ 696 ConstrainColormapIndex(image,index,exception)].red,q); 697 index=(ssize_t) GetPixelGreen(image,q); 698 SetPixelGreen(image,image->colormap[ 699 ConstrainColormapIndex(image,index,exception)].green,q); 700 index=(ssize_t) GetPixelBlue(image,q); 701 SetPixelBlue(image,image->colormap[ 702 ConstrainColormapIndex(image,index,exception)].blue,q); 703 } 704 SetPixelAlpha(image,image->alpha_trait != UndefinedPixelTrait ? 705 ScaleCharToQuantum(*(p+number_pixels*3)) : OpaqueAlpha,q); 706 p++; 707 q+=GetPixelChannels(image); 708 } 709 if (SyncAuthenticPixels(image,exception) == MagickFalse) 710 break; 711 if (image->previous == (Image *) NULL) 712 { 713 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 714 image->rows); 715 if (status == MagickFalse) 716 break; 717 } 718 } 719 } 720 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 721 if (image->storage_class == PseudoClass) 722 (void) SyncImage(image,exception); 723 if (EOFBlob(image) != MagickFalse) 724 { 725 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 726 image->filename); 727 break; 728 } 729 /* 730 Proceed to next image. 731 */ 732 if (image_info->number_scenes != 0) 733 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 734 break; 735 count=ReadBlob(image,1,&viff_info.identifier); 736 if ((count != 0) && (viff_info.identifier == 0xab)) 737 { 738 /* 739 Allocate next image structure. 740 */ 741 AcquireNextImage(image_info,image,exception); 742 if (GetNextImageInList(image) == (Image *) NULL) 743 { 744 image=DestroyImageList(image); 745 return((Image *) NULL); 746 } 747 image=SyncNextImageInList(image); 748 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 749 GetBlobSize(image)); 750 if (status == MagickFalse) 751 break; 752 } 753 } while ((count != 0) && (viff_info.identifier == 0xab)); 754 (void) CloseBlob(image); 755 return(GetFirstImageInList(image)); 756} 757 758/* 759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 760% % 761% % 762% % 763% R e g i s t e r V I F F I m a g e % 764% % 765% % 766% % 767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 768% 769% RegisterVIFFImage() adds properties for the VIFF image format to 770% the list of supported formats. The properties include the image format 771% tag, a method to read and/or write the format, whether the format 772% supports the saving of more than one frame to the same file or blob, 773% whether the format supports native in-memory I/O, and a brief 774% description of the format. 775% 776% The format of the RegisterVIFFImage method is: 777% 778% size_t RegisterVIFFImage(void) 779% 780*/ 781ModuleExport size_t RegisterVIFFImage(void) 782{ 783 MagickInfo 784 *entry; 785 786 entry=AcquireMagickInfo("VIFF","VIFF","Khoros Visualization image"); 787 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 788 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 789 entry->magick=(IsImageFormatHandler *) IsVIFF; 790 (void) RegisterMagickInfo(entry); 791 entry=AcquireMagickInfo("VIFF","XV","Khoros Visualization image"); 792 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 793 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 794 (void) RegisterMagickInfo(entry); 795 return(MagickImageCoderSignature); 796} 797 798/* 799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 800% % 801% % 802% % 803% U n r e g i s t e r V I F F I m a g e % 804% % 805% % 806% % 807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 808% 809% UnregisterVIFFImage() removes format registrations made by the 810% VIFF module from the list of supported formats. 811% 812% The format of the UnregisterVIFFImage method is: 813% 814% UnregisterVIFFImage(void) 815% 816*/ 817ModuleExport void UnregisterVIFFImage(void) 818{ 819 (void) UnregisterMagickInfo("VIFF"); 820 (void) UnregisterMagickInfo("XV"); 821} 822 823/* 824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 825% % 826% % 827% % 828% W r i t e V I F F I m a g e % 829% % 830% % 831% % 832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 833% 834% WriteVIFFImage() writes an image to a file in the VIFF image format. 835% 836% The format of the WriteVIFFImage method is: 837% 838% MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 839% Image *image,ExceptionInfo *exception) 840% 841% A description of each parameter follows. 842% 843% o image_info: the image info. 844% 845% o image: The image. 846% 847% o exception: return any errors or warnings in this structure. 848% 849*/ 850static MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 851 Image *image,ExceptionInfo *exception) 852{ 853#define VFF_CM_genericRGB 15 854#define VFF_CM_NONE 0 855#define VFF_DEP_IEEEORDER 0x2 856#define VFF_DES_RAW 0 857#define VFF_LOC_IMPLICIT 1 858#define VFF_MAPTYP_NONE 0 859#define VFF_MAPTYP_1_BYTE 1 860#define VFF_MS_NONE 0 861#define VFF_MS_ONEPERBAND 1 862#define VFF_TYP_BIT 0 863#define VFF_TYP_1_BYTE 1 864 865 typedef struct _ViffInfo 866 { 867 char 868 identifier, 869 file_type, 870 release, 871 version, 872 machine_dependency, 873 reserve[3], 874 comment[512]; 875 876 size_t 877 rows, 878 columns, 879 subrows; 880 881 int 882 x_offset, 883 y_offset; 884 885 unsigned int 886 x_bits_per_pixel, 887 y_bits_per_pixel, 888 location_type, 889 location_dimension, 890 number_of_images, 891 number_data_bands, 892 data_storage_type, 893 data_encode_scheme, 894 map_scheme, 895 map_storage_type, 896 map_rows, 897 map_columns, 898 map_subrows, 899 map_enable, 900 maps_per_cycle, 901 color_space_model; 902 } ViffInfo; 903 904 const char 905 *value; 906 907 MagickBooleanType 908 status; 909 910 MagickOffsetType 911 scene; 912 913 MagickSizeType 914 number_pixels, 915 packets; 916 917 MemoryInfo 918 *pixel_info; 919 920 register const Quantum 921 *p; 922 923 register ssize_t 924 x; 925 926 register ssize_t 927 i; 928 929 register unsigned char 930 *q; 931 932 ssize_t 933 y; 934 935 unsigned char 936 *pixels; 937 938 ViffInfo 939 viff_info; 940 941 /* 942 Open output image file. 943 */ 944 assert(image_info != (const ImageInfo *) NULL); 945 assert(image_info->signature == MagickSignature); 946 assert(image != (Image *) NULL); 947 assert(image->signature == MagickSignature); 948 if (image->debug != MagickFalse) 949 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 950 assert(exception != (ExceptionInfo *) NULL); 951 assert(exception->signature == MagickSignature); 952 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 953 if (status == MagickFalse) 954 return(status); 955 (void) ResetMagickMemory(&viff_info,0,sizeof(ViffInfo)); 956 scene=0; 957 do 958 { 959 /* 960 Initialize VIFF image structure. 961 */ 962 (void) TransformImageColorspace(image,sRGBColorspace,exception); 963DisableMSCWarning(4310) 964 viff_info.identifier=(char) 0xab; 965RestoreMSCWarning 966 viff_info.file_type=1; 967 viff_info.release=1; 968 viff_info.version=3; 969 viff_info.machine_dependency=VFF_DEP_IEEEORDER; /* IEEE byte ordering */ 970 *viff_info.comment='\0'; 971 value=GetImageProperty(image,"comment",exception); 972 if (value != (const char *) NULL) 973 (void) CopyMagickString(viff_info.comment,value,MagickMin(strlen(value), 974 511)+1); 975 viff_info.rows=image->columns; 976 viff_info.columns=image->rows; 977 viff_info.subrows=0; 978 viff_info.x_offset=(~0); 979 viff_info.y_offset=(~0); 980 viff_info.x_bits_per_pixel=0; 981 viff_info.y_bits_per_pixel=0; 982 viff_info.location_type=VFF_LOC_IMPLICIT; 983 viff_info.location_dimension=0; 984 viff_info.number_of_images=1; 985 viff_info.data_encode_scheme=VFF_DES_RAW; 986 viff_info.map_scheme=VFF_MS_NONE; 987 viff_info.map_storage_type=VFF_MAPTYP_NONE; 988 viff_info.map_rows=0; 989 viff_info.map_columns=0; 990 viff_info.map_subrows=0; 991 viff_info.map_enable=1; /* no colormap */ 992 viff_info.maps_per_cycle=0; 993 number_pixels=(MagickSizeType) image->columns*image->rows; 994 if (image->storage_class == DirectClass) 995 { 996 /* 997 Full color VIFF raster. 998 */ 999 viff_info.number_data_bands=image->alpha_trait ? 4U : 3U; 1000 viff_info.color_space_model=VFF_CM_genericRGB; 1001 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1002 packets=viff_info.number_data_bands*number_pixels; 1003 } 1004 else 1005 { 1006 viff_info.number_data_bands=1; 1007 viff_info.color_space_model=VFF_CM_NONE; 1008 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1009 packets=number_pixels; 1010 if (SetImageGray(image,exception) == MagickFalse) 1011 { 1012 /* 1013 Colormapped VIFF raster. 1014 */ 1015 viff_info.map_scheme=VFF_MS_ONEPERBAND; 1016 viff_info.map_storage_type=VFF_MAPTYP_1_BYTE; 1017 viff_info.map_rows=3; 1018 viff_info.map_columns=(unsigned int) image->colors; 1019 } 1020 else 1021 if (image->colors <= 2) 1022 { 1023 /* 1024 Monochrome VIFF raster. 1025 */ 1026 viff_info.data_storage_type=VFF_TYP_BIT; 1027 packets=((image->columns+7) >> 3)*image->rows; 1028 } 1029 } 1030 /* 1031 Write VIFF image header (pad to 1024 bytes). 1032 */ 1033 (void) WriteBlob(image,sizeof(viff_info.identifier),(unsigned char *) 1034 &viff_info.identifier); 1035 (void) WriteBlob(image,sizeof(viff_info.file_type),(unsigned char *) 1036 &viff_info.file_type); 1037 (void) WriteBlob(image,sizeof(viff_info.release),(unsigned char *) 1038 &viff_info.release); 1039 (void) WriteBlob(image,sizeof(viff_info.version),(unsigned char *) 1040 &viff_info.version); 1041 (void) WriteBlob(image,sizeof(viff_info.machine_dependency), 1042 (unsigned char *) &viff_info.machine_dependency); 1043 (void) WriteBlob(image,sizeof(viff_info.reserve),(unsigned char *) 1044 viff_info.reserve); 1045 (void) WriteBlob(image,512,(unsigned char *) viff_info.comment); 1046 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.rows); 1047 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.columns); 1048 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.subrows); 1049 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_offset); 1050 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_offset); 1051 viff_info.x_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16)); 1052 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_bits_per_pixel); 1053 viff_info.y_bits_per_pixel=(unsigned int) ((63 << 24) | (128 << 16)); 1054 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_bits_per_pixel); 1055 (void) WriteBlobMSBLong(image,viff_info.location_type); 1056 (void) WriteBlobMSBLong(image,viff_info.location_dimension); 1057 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_of_images); 1058 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_data_bands); 1059 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_storage_type); 1060 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_encode_scheme); 1061 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_scheme); 1062 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_storage_type); 1063 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_rows); 1064 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_columns); 1065 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_subrows); 1066 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable); 1067 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle); 1068 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model); 1069 for (i=0; i < 420; i++) 1070 (void) WriteBlobByte(image,'\0'); 1071 /* 1072 Convert MIFF to VIFF raster pixels. 1073 */ 1074 pixel_info=AcquireVirtualMemory((size_t) packets,sizeof(*pixels)); 1075 if (pixel_info == (MemoryInfo *) NULL) 1076 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1077 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1078 q=pixels; 1079 if (image->storage_class == DirectClass) 1080 { 1081 /* 1082 Convert DirectClass packet to VIFF RGB pixel. 1083 */ 1084 number_pixels=(MagickSizeType) image->columns*image->rows; 1085 for (y=0; y < (ssize_t) image->rows; y++) 1086 { 1087 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1088 if (p == (const Quantum *) NULL) 1089 break; 1090 for (x=0; x < (ssize_t) image->columns; x++) 1091 { 1092 *q=ScaleQuantumToChar(GetPixelRed(image,p)); 1093 *(q+number_pixels)=ScaleQuantumToChar(GetPixelGreen(image,p)); 1094 *(q+number_pixels*2)=ScaleQuantumToChar(GetPixelBlue(image,p)); 1095 if (image->alpha_trait != UndefinedPixelTrait) 1096 *(q+number_pixels*3)=ScaleQuantumToChar((Quantum) 1097 (GetPixelAlpha(image,p))); 1098 p+=GetPixelChannels(image); 1099 q++; 1100 } 1101 if (image->previous == (Image *) NULL) 1102 { 1103 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1104 image->rows); 1105 if (status == MagickFalse) 1106 break; 1107 } 1108 } 1109 } 1110 else 1111 if (SetImageGray(image,exception) == MagickFalse) 1112 { 1113 unsigned char 1114 *viff_colormap; 1115 1116 /* 1117 Dump colormap to file. 1118 */ 1119 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 1120 3*sizeof(*viff_colormap)); 1121 if (viff_colormap == (unsigned char *) NULL) 1122 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1123 q=viff_colormap; 1124 for (i=0; i < (ssize_t) image->colors; i++) 1125 *q++=ScaleQuantumToChar(image->colormap[i].red); 1126 for (i=0; i < (ssize_t) image->colors; i++) 1127 *q++=ScaleQuantumToChar(image->colormap[i].green); 1128 for (i=0; i < (ssize_t) image->colors; i++) 1129 *q++=ScaleQuantumToChar(image->colormap[i].blue); 1130 (void) WriteBlob(image,3*image->colors,viff_colormap); 1131 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 1132 /* 1133 Convert PseudoClass packet to VIFF colormapped pixels. 1134 */ 1135 q=pixels; 1136 for (y=0; y < (ssize_t) image->rows; y++) 1137 { 1138 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1139 if (p == (const Quantum *) NULL) 1140 break; 1141 for (x=0; x < (ssize_t) image->columns; x++) 1142 { 1143 *q++=(unsigned char) GetPixelIndex(image,p); 1144 p+=GetPixelChannels(image); 1145 } 1146 if (image->previous == (Image *) NULL) 1147 { 1148 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1149 image->rows); 1150 if (status == MagickFalse) 1151 break; 1152 } 1153 } 1154 } 1155 else 1156 if (image->colors <= 2) 1157 { 1158 ssize_t 1159 x, 1160 y; 1161 1162 register unsigned char 1163 bit, 1164 byte; 1165 1166 /* 1167 Convert PseudoClass image to a VIFF monochrome image. 1168 */ 1169 (void) SetImageType(image,BilevelType,exception); 1170 for (y=0; y < (ssize_t) image->rows; y++) 1171 { 1172 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1173 if (p == (const Quantum *) NULL) 1174 break; 1175 bit=0; 1176 byte=0; 1177 for (x=0; x < (ssize_t) image->columns; x++) 1178 { 1179 byte>>=1; 1180 if (GetPixelLuma(image,p) < (QuantumRange/2.0)) 1181 byte|=0x80; 1182 bit++; 1183 if (bit == 8) 1184 { 1185 *q++=byte; 1186 bit=0; 1187 byte=0; 1188 } 1189 p+=GetPixelChannels(image); 1190 } 1191 if (bit != 0) 1192 *q++=byte >> (8-bit); 1193 if (image->previous == (Image *) NULL) 1194 { 1195 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1196 y,image->rows); 1197 if (status == MagickFalse) 1198 break; 1199 } 1200 } 1201 } 1202 else 1203 { 1204 /* 1205 Convert PseudoClass packet to VIFF grayscale pixel. 1206 */ 1207 for (y=0; y < (ssize_t) image->rows; y++) 1208 { 1209 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1210 if (p == (const Quantum *) NULL) 1211 break; 1212 for (x=0; x < (ssize_t) image->columns; x++) 1213 { 1214 *q++=(unsigned char) ClampToQuantum(GetPixelLuma(image,p)); 1215 p+=GetPixelChannels(image); 1216 } 1217 if (image->previous == (Image *) NULL) 1218 { 1219 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1220 y,image->rows); 1221 if (status == MagickFalse) 1222 break; 1223 } 1224 } 1225 } 1226 (void) WriteBlob(image,(size_t) packets,pixels); 1227 pixel_info=RelinquishVirtualMemory(pixel_info); 1228 if (GetNextImageInList(image) == (Image *) NULL) 1229 break; 1230 image=SyncNextImageInList(image); 1231 status=SetImageProgress(image,SaveImagesTag,scene++, 1232 GetImageListLength(image)); 1233 if (status == MagickFalse) 1234 break; 1235 } while (image_info->adjoin != MagickFalse); 1236 (void) CloseBlob(image); 1237 return(MagickTrue); 1238} 1239