1 /*****************************************************************************/ 2 // SGITranslator 3 // Written by Stephan Aßmus <stippi@yellowbites.com> 4 // derived from GIMP SGI plugin by Michael Sweet 5 // 6 // SGIImage.cpp 7 // 8 // SGI image file format library routines. 9 // 10 // Formed into a class SGIImage, adopted to Be API and modified to use 11 // BPositionIO, optimizations for buffered reading. 12 // 13 // 14 // Copyright (c) 2003 OpenBeOS Project 15 // Portions Copyright 1997-1998 Michael Sweet (mike@easysw.com) 16 // 17 // Permission is hereby granted, free of charge, to any person obtaining a 18 // copy of this software and associated documentation files (the "Software"), 19 // to deal in the Software without restriction, including without limitation 20 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 21 // and/or sell copies of the Software, and to permit persons to whom the 22 // Software is furnished to do so, subject to the following conditions: 23 // 24 // The above copyright notice and this permission notice shall be included 25 // in all copies or substantial portions of the Software. 26 // 27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 33 // DEALINGS IN THE SOFTWARE. 34 /*****************************************************************************/ 35 36 #include <malloc.h> 37 #include <stdio.h> 38 #include <string.h> 39 40 #include <ByteOrder.h> 41 #include <DataIO.h> 42 #include <TranslationErrors.h> 43 44 #include "SGIImage.h" 45 46 const char kSGICopyright[] = ""B_UTF8_COPYRIGHT" 1997-1998 Michael Sweet <mike@easysw.com>"; 47 48 // constructor 49 SGIImage::SGIImage() 50 : fStream(NULL), 51 fMode(0), 52 fBytesPerChannel(0), 53 fCompression(0), 54 fWidth(0), 55 fHeight(0), 56 fChannelCount(0), 57 fFirstRowOffset(0), 58 fNextRowOffset(0), 59 fOffsetTable(NULL), 60 fLengthTable(NULL), 61 fARLERow(NULL), 62 fARLEOffset(0), 63 fARLELength(0) 64 { 65 } 66 67 // destructor 68 SGIImage::~SGIImage() 69 { 70 Unset(); 71 } 72 73 // InitCheck 74 status_t 75 SGIImage::InitCheck() const 76 { 77 if (fStream) 78 return B_OK; 79 return B_NO_INIT; 80 } 81 82 // SetTo 83 // open an SGI image file for reading 84 // 85 // stream the input stream 86 status_t 87 SGIImage::SetTo(BPositionIO* stream) 88 { 89 if (!stream) 90 return B_BAD_VALUE; 91 92 fStream = stream; 93 stream->Seek(0, SEEK_SET); 94 95 int16 magic = _ReadShort(); 96 if (magic != SGI_MAGIC) { 97 fStream = NULL; 98 return B_NO_TRANSLATOR; 99 } 100 101 fMode = SGI_READ; 102 103 fCompression = _ReadChar(); 104 fBytesPerChannel = _ReadChar(); 105 _ReadShort(); // Dimensions 106 fWidth = _ReadShort(); 107 fHeight = _ReadShort(); 108 fChannelCount = _ReadShort(); 109 // _ReadLong(); // Minimum pixel 110 // _ReadLong(); // Maximum pixel 111 112 if (fCompression) { 113 // this stream is compressed; read the scanline tables... 114 115 fStream->Seek(512, SEEK_SET); 116 117 fOffsetTable = (int32**)calloc(fChannelCount, sizeof(int32*)); 118 fOffsetTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); 119 for (uint32 i = 1; i < fChannelCount; i++) 120 fOffsetTable[i] = fOffsetTable[0] + i * fHeight; 121 122 for (uint32 i = 0; i < fChannelCount; i++) 123 for (uint16 j = 0; j < fHeight; j++) 124 fOffsetTable[i][j] = _ReadLong(); 125 126 fLengthTable = (int32**)calloc(fChannelCount, sizeof(int32*)); 127 fLengthTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); 128 129 for (int32 i = 1; i < fChannelCount; i ++) 130 fLengthTable[i] = fLengthTable[0] + i * fHeight; 131 132 for (uint32 i = 0; i < fChannelCount; i++) 133 for (uint16 j = 0; j < fHeight; j++) 134 fLengthTable[i][j] = _ReadLong(); 135 136 } 137 return B_OK; 138 } 139 140 // SetTo 141 // open an SGI image file for writing 142 // 143 // stream the output stream 144 // width number of pixels in a row 145 // height number of rows 146 // channels number of channels per pixel 147 // bytesPerChannel number of bytes per channel 148 // compression compression mode 149 status_t 150 SGIImage::SetTo(BPositionIO* stream, 151 uint16 width, uint16 height, 152 uint16 channels, uint32 bytesPerChannel, 153 uint32 compression) 154 { 155 // sanity checks 156 if (!stream || 157 width < 1 || height < 1 || channels < 1 || 158 bytesPerChannel < 1 || bytesPerChannel > 2 || 159 compression < SGI_COMP_NONE || compression > SGI_COMP_ARLE) 160 return B_BAD_VALUE; 161 162 fStream = stream; 163 fMode = SGI_WRITE; 164 165 _WriteShort(SGI_MAGIC); 166 _WriteChar((fCompression = compression) != 0); 167 _WriteChar(fBytesPerChannel = bytesPerChannel); 168 _WriteShort(3); // Dimensions 169 _WriteShort(fWidth = width); 170 _WriteShort(fHeight = height); 171 _WriteShort(fChannelCount = channels); 172 173 if (fBytesPerChannel == 1) { 174 _WriteLong(0); // Minimum pixel 175 _WriteLong(255); // Maximum pixel 176 } else { 177 _WriteLong(-32768); // Minimum pixel 178 _WriteLong(32767); // Maximum pixel 179 } 180 _WriteLong(0); // Reserved 181 182 char name[80]; // Name of file in image header 183 memset(name, 0, sizeof(name)); 184 sprintf(name, "OpenBeOS SGITranslator"); 185 fStream->Write(name, sizeof(name)); 186 187 // fill the rest of the image header with zeros 188 for (int32 i = 0; i < 102; i++) 189 _WriteLong(0); 190 191 switch (fCompression) { 192 case SGI_COMP_NONE : // No compression 193 // This file is uncompressed. To avoid problems with 194 // sparse files, we need to write blank pixels for the 195 // entire image... 196 197 /* if (fBytesPerChannel == 1) { 198 for (int32 i = fWidth * fHeight * fChannelCount; i > 0; i --) 199 _WriteChar(0); 200 } else { 201 for (int32 i = fWidth * fHeight * fChannelCount; i > 0; i --) 202 _WriteShort(0); 203 }*/ 204 break; 205 206 case SGI_COMP_ARLE: // Aggressive RLE 207 fARLERow = (uint16*)calloc(fWidth, sizeof(uint16)); 208 fARLEOffset = 0; 209 // FALL THROUGH 210 case SGI_COMP_RLE : // Run-Length Encoding 211 // This file is compressed; write the (blank) scanline tables... 212 213 // for (int32 i = 2 * fHeight * fChannelCount; i > 0; i--) 214 // _WriteLong(0); 215 fStream->Seek(2 * fHeight * fChannelCount * sizeof(int32), SEEK_CUR); 216 217 fFirstRowOffset = fStream->Position(); 218 fNextRowOffset = fStream->Position(); 219 220 // allocate and read offset table 221 fOffsetTable = (int32**)calloc(fChannelCount, sizeof(int32*)); 222 fOffsetTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); 223 224 for (int32 i = 1; i < fChannelCount; i ++) 225 fOffsetTable[i] = fOffsetTable[0] + i * fHeight; 226 227 // allocate and read length table 228 fLengthTable = (int32**)calloc(fChannelCount, sizeof(int32*)); 229 fLengthTable[0] = (int32*)calloc(fHeight * fChannelCount, sizeof(int32)); 230 231 for (int32 i = 1; i < fChannelCount; i ++) 232 fLengthTable[i] = fLengthTable[0] + i * fHeight; 233 break; 234 } 235 return B_OK; 236 } 237 238 // Unset 239 // 240 // if in write mode, writes final information to the stream 241 status_t 242 SGIImage::Unset() 243 { 244 status_t ret = InitCheck(); // return status 245 if (ret >= B_OK) { 246 247 if (fMode == SGI_WRITE && fCompression != SGI_COMP_NONE) { 248 // write the scanline offset table to the file... 249 250 fStream->Seek(512, SEEK_SET); 251 252 /* off_t* offset = fOffsetTable[0]; 253 for (int32 i = fHeight * fChannelCount; i > 0; i--) { 254 if ((ret = _WriteLong(offset[0])) < B_OK) 255 break; 256 offset++; 257 }*/ 258 259 int32 size = fHeight * fChannelCount * sizeof(int32); 260 swap_data(B_INT32_TYPE, fOffsetTable[0], size, B_SWAP_HOST_TO_BENDIAN); 261 ret = fStream->Write(fOffsetTable[0], size); 262 263 if (ret >= B_OK) { 264 265 /* int32* length = fLengthTable[0]; 266 for (int32 i = fHeight * fChannelCount; i > 0; i--) { 267 if ((ret = _WriteLong(length[0])) < B_OK) 268 break; 269 length++; 270 }*/ 271 272 swap_data(B_INT32_TYPE, fLengthTable[0], size, B_SWAP_HOST_TO_BENDIAN); 273 ret = fStream->Write(fLengthTable[0], size); 274 275 } 276 } 277 278 if (fOffsetTable != NULL) { 279 free(fOffsetTable[0]); 280 free(fOffsetTable); 281 fOffsetTable = NULL; 282 } 283 284 if (fLengthTable != NULL) { 285 free(fLengthTable[0]); 286 free(fLengthTable); 287 fLengthTable = NULL; 288 } 289 290 if (fARLERow) { 291 free(fARLERow); 292 fARLERow = NULL; 293 } 294 295 fStream = NULL; 296 } 297 return ret; 298 } 299 300 // ReadRow 301 // 302 // reads a row of image data from the stream 303 // 304 // row pointer to buffer (row of pixels) to read 305 // y index (line number) of this row 306 // z which channel to read 307 status_t 308 SGIImage::ReadRow(void* row, int32 y, int32 z) 309 { 310 // sanitiy checks 311 if (row == NULL || 312 y < 0 || y >= fHeight || 313 z < 0 || z >= fChannelCount) 314 return B_BAD_VALUE; 315 316 317 status_t ret = B_ERROR; 318 319 switch (fCompression) { 320 case SGI_COMP_NONE: { 321 // seek to the image row 322 // optimize buffering by only seeking if necessary... 323 324 off_t offset = 512 + (y + z * fHeight) * fWidth * fBytesPerChannel; 325 fStream->Seek(offset, SEEK_SET); 326 327 uint32 bytes = fWidth * fBytesPerChannel; 328 //printf("reading %ld bytes 8 Bit uncompressed row: %ld, channel: %ld\n", bytes, y, z); 329 ret = fStream->Read(row, bytes); 330 331 break; 332 } 333 case SGI_COMP_RLE: { 334 int32 offset = fOffsetTable[z][y]; 335 int32 rleLength = fLengthTable[z][y]; 336 fStream->Seek(offset, SEEK_SET); 337 uint8* rleBuffer = new uint8[rleLength]; 338 fStream->Read(rleBuffer, rleLength); 339 340 if (fBytesPerChannel == 1) { 341 //printf("reading 8 Bit RLE compressed row: %ld, channel: %ld\n", y, z); 342 // ret = _ReadRLE8((uint8*)row, fWidth); 343 ret = _ReadRLE8((uint8*)row, rleBuffer, fWidth); 344 } else { 345 //printf("reading 16 Bit RLE compressed row: %ld, channel: %ld\n", y, z); 346 // ret = _ReadRLE16((uint16*)row, fWidth); 347 if ((ret = swap_data(B_INT16_TYPE, rleBuffer, rleLength, B_SWAP_BENDIAN_TO_HOST)) >= B_OK) 348 ret = _ReadRLE16((uint16*)row, (uint16*)rleBuffer, fWidth); 349 } 350 delete[] rleBuffer; 351 break; 352 } 353 } 354 return ret; 355 } 356 357 // WriteRow 358 // 359 // writes a row of image data to the stream 360 // 361 // row pointer to buffer (row of pixels) to write 362 // y index (line number) of this row 363 // z which channel to write 364 status_t 365 SGIImage::WriteRow(void* row, int32 y, int32 z) 366 { 367 // sanitiy checks 368 if (row == NULL || 369 y < 0 || y >= fHeight || 370 z < 0 || z >= fChannelCount) 371 return B_BAD_VALUE; 372 373 int32 x; // x coordinate 374 int32 offset; // stream offset 375 376 status_t ret = B_ERROR; 377 378 switch (fCompression) { 379 case SGI_COMP_NONE: { 380 // Seek to the image row 381 382 offset = 512 + (y + z * fHeight) * fWidth * fBytesPerChannel; 383 fStream->Seek(offset, SEEK_SET); 384 385 uint32 bytes = fWidth * fBytesPerChannel; 386 //printf("writing %ld bytes %ld byte/channel uncompressed row: %ld, channel: %ld\n", bytes, fBytesPerChannel, y, z); 387 ret = fStream->Write(row, bytes); 388 /* if (fBytesPerChannel == 1) { 389 for (x = fWidth; x > 0; x--) { 390 _WriteChar(*row); 391 row++; 392 } 393 } else { 394 for (x = fWidth; x > 0; x--) { 395 _WriteShort(*row); 396 row++; 397 } 398 }*/ 399 break; 400 } 401 case SGI_COMP_ARLE: 402 if (fOffsetTable[z][y] != 0) 403 return B_ERROR; 404 405 // First check the last row written... 406 407 if (fARLEOffset > 0) { 408 if (fBytesPerChannel == 1) { 409 uint8* arleRow = (uint8*)fARLERow; 410 uint8* src = (uint8*)row; 411 for (x = 0; x < fWidth; x++) 412 if (*src++ != *arleRow++) 413 break; 414 } else { 415 uint16* arleRow = (uint16*)fARLERow; 416 uint16* src = (uint16*)row; 417 for (x = 0; x < fWidth; x++) 418 if (*src++ != *arleRow++) 419 break; 420 } 421 422 if (x == fWidth) { 423 fOffsetTable[z][y] = fARLEOffset; 424 fLengthTable[z][y] = fARLELength; 425 return B_OK; 426 } 427 } 428 429 // If that didn't match, search all the previous rows... 430 431 fStream->Seek(fFirstRowOffset, SEEK_SET); 432 433 if (fBytesPerChannel == 1) { 434 do { 435 fARLEOffset = fStream->Position(); 436 437 uint8* arleRow = (uint8*)fARLERow; 438 if ((fARLELength = _ReadRLE8(arleRow, fWidth)) < B_OK) { 439 x = 0; 440 break; 441 } 442 443 uint8* src = (uint8*)row; 444 for (x = 0; x < fWidth; x++) 445 if (*src++ != *arleRow++) 446 break; 447 } while (x < fWidth); 448 } else { 449 do { 450 fARLEOffset = fStream->Position(); 451 452 uint16* arleRow = (uint16*)fARLERow; 453 if ((fARLELength = _ReadRLE16(arleRow, fWidth)) < B_OK) { 454 x = 0; 455 break; 456 } 457 458 uint16* src = (uint16*)row; 459 for (x = 0; x < fWidth; x++) 460 if (*src++ != *arleRow++) 461 break; 462 } while (x < fWidth); 463 } 464 465 if (x == fWidth) { 466 fOffsetTable[z][y] = fARLEOffset; 467 fLengthTable[z][y] = fARLELength; 468 return B_OK; 469 } else 470 fStream->Seek(0, SEEK_END); // seek to end of stream 471 // FALL THROUGH! 472 case SGI_COMP_RLE : 473 if (fOffsetTable[z][y] != 0) 474 return B_ERROR; 475 476 offset = fOffsetTable[z][y] = fNextRowOffset; 477 478 if (offset != fStream->Position()) 479 fStream->Seek(offset, SEEK_SET); 480 481 //printf("writing %d pixels %ld byte/channel RLE row: %ld, channel: %ld\n", fWidth, fBytesPerChannel, y, z); 482 483 if (fBytesPerChannel == 1) 484 x = _WriteRLE8((uint8*)row, fWidth); 485 else 486 x = _WriteRLE16((uint16*)row, fWidth); 487 488 if (fCompression == SGI_COMP_ARLE) { 489 fARLEOffset = offset; 490 fARLELength = x; 491 memcpy(fARLERow, row, fWidth * fBytesPerChannel); 492 } 493 494 fNextRowOffset = fStream->Position(); 495 fLengthTable[z][y] = x; 496 497 return x; 498 default: 499 break; 500 } 501 502 return ret; 503 } 504 505 // _ReadLong 506 // 507 // reads 4 bytes from the stream and 508 // returns a 32-bit big-endian integer 509 int32 510 SGIImage::_ReadLong() const 511 { 512 int32 n; 513 if (fStream->Read(&n, 4) == 4) { 514 return B_BENDIAN_TO_HOST_INT32(n); 515 } else 516 return 0; 517 } 518 519 // _ReadShort 520 // 521 // reads 2 bytes from the stream and 522 // returns a 16-bit big-endian integer 523 int16 524 SGIImage::_ReadShort() const 525 { 526 int16 n; 527 if (fStream->Read(&n, 2) == 2) { 528 return B_BENDIAN_TO_HOST_INT16(n); 529 } else 530 return 0; 531 } 532 533 // _ReadChar 534 // 535 // reads 1 byte from the stream and 536 // returns it 537 int8 538 SGIImage::_ReadChar() const 539 { 540 int8 b; 541 ssize_t read = fStream->Read(&b, 1); 542 if (read == 1) 543 return b; 544 else if (read < B_OK) 545 return (int8)read; 546 return (int8)B_ERROR; 547 } 548 549 // _WriteLong 550 // 551 // writes a 32-bit big-endian integer to the stream 552 status_t 553 SGIImage::_WriteLong(int32 n) const 554 { 555 int32 bigN = B_HOST_TO_BENDIAN_INT32(n); 556 ssize_t written = fStream->Write(&bigN, sizeof(int32)); 557 if (written == sizeof(int32)) 558 return B_OK; 559 if (written < B_OK) 560 return written; 561 return B_ERROR; 562 } 563 564 // _WriteShort 565 // 566 // writes a 16-bit big-endian integer to the stream 567 status_t 568 SGIImage::_WriteShort(uint16 n) const 569 { 570 uint16 bigN = B_HOST_TO_BENDIAN_INT16(n); 571 ssize_t written = fStream->Write(&bigN, sizeof(uint16)); 572 if (written == sizeof(uint16)) 573 return B_OK; 574 if (written < B_OK) 575 return written; 576 return B_ERROR; 577 } 578 579 // _WriteChar 580 // 581 // writes one byte to the stream 582 status_t 583 SGIImage::_WriteChar(int8 n) const 584 { 585 ssize_t written = fStream->Write(&n, sizeof(int8)); 586 if (written == sizeof(int8)) 587 return B_OK; 588 if (written < B_OK) 589 return written; 590 return B_ERROR; 591 } 592 593 // _ReadRLE8 594 // 595 // reads 8-bit RLE data into provided buffer 596 // 597 // row pointer to buffer for one row 598 // numPixels number of pixels that fit into row buffer 599 ssize_t 600 SGIImage::_ReadRLE8(uint8* row, int32 numPixels) const 601 { 602 int32 ch; // current charater 603 uint32 count; // RLE count 604 uint32 length = 0; // number of bytes read 605 606 uint32 bufferSize = 1024; 607 uint8* buffer = new uint8[bufferSize]; 608 uint32 bufferPos = bufferSize; 609 610 status_t ret = B_OK; 611 612 while (numPixels > 0) { 613 614 // fetch another buffer if we need to 615 if (bufferPos >= bufferSize) { 616 ret = fStream->Read(buffer, bufferSize); 617 if (ret < B_OK) 618 break; 619 else 620 bufferPos = 0; 621 } 622 623 ch = buffer[bufferPos ++]; 624 length ++; 625 626 count = ch & 127; 627 if (count == 0) 628 break; 629 630 if (ch & 128) { 631 for (uint32 i = 0; i < count; i++) { 632 633 // fetch another buffer if we need to 634 if (bufferPos >= bufferSize) { 635 ret = fStream->Read(buffer, bufferSize); 636 if (ret < B_OK) { 637 delete[] buffer; 638 return ret; 639 } else 640 bufferPos = 0; 641 } 642 643 *row = buffer[bufferPos ++]; 644 row ++; 645 numPixels --; 646 length ++; 647 } 648 } else { 649 650 // fetch another buffer if we need to 651 if (bufferPos >= bufferSize) { 652 ret = fStream->Read(buffer, bufferSize); 653 if (ret < B_OK) { 654 delete[] buffer; 655 return ret; 656 } else 657 bufferPos = 0; 658 } 659 660 ch = buffer[bufferPos ++]; 661 length ++; 662 for (uint32 i = 0; i < count; i++) { 663 *row = ch; 664 row ++; 665 numPixels --; 666 } 667 } 668 } 669 delete[] buffer; 670 671 return (numPixels > 0 ? ret : length); 672 } 673 674 // _ReadRLE8 675 // 676 // reads 8-bit RLE data into provided buffer 677 // 678 // row pointer to buffer for one row 679 // numPixels number of pixels that fit into row buffer 680 ssize_t 681 SGIImage::_ReadRLE8(uint8* row, uint8* rleBuffer, int32 numPixels) const 682 { 683 int32 ch; // current charater 684 uint32 count; // RLE count 685 uint32 length = 0; // number of bytes read 686 687 if (numPixels <= 0) 688 return B_ERROR; 689 690 while (numPixels > 0) { 691 692 ch = *rleBuffer ++; 693 length ++; 694 695 count = ch & 127; 696 if (count == 0) 697 break; 698 699 if (ch & 128) { 700 for (uint32 i = 0; i < count; i++) { 701 702 *row = *rleBuffer ++; 703 row ++; 704 numPixels --; 705 length ++; 706 } 707 } else { 708 709 ch = *rleBuffer ++; 710 length ++; 711 for (uint32 i = 0; i < count; i++) { 712 *row = ch; 713 row ++; 714 numPixels --; 715 } 716 } 717 } 718 719 return length; 720 } 721 /*ssize_t 722 SGIImage::_ReadRLE8(uint8* row, int32 numPixels) const 723 { 724 int32 ch; // current charater 725 uint32 count; // RLE count 726 uint32 length = 0; // number of bytes read 727 728 while (numPixels > 0) { 729 ch = _ReadChar(); 730 length ++; 731 732 count = ch & 127; 733 if (count == 0) 734 break; 735 736 if (ch & 128) { 737 for (uint32 i = 0; i < count; i++) { 738 *row = _ReadChar(); 739 row ++; 740 numPixels --; 741 length ++; 742 } 743 } else { 744 ch = _ReadChar(); 745 length ++; 746 for (uint32 i = 0; i < count; i++) { 747 *row = ch; 748 row ++; 749 numPixels --; 750 } 751 } 752 } 753 return (numPixels > 0 ? B_ERROR : length); 754 }*/ 755 756 // read_and_swap 757 status_t 758 read_and_swap(BPositionIO* stream, int16* buffer, uint32 size) 759 { 760 status_t ret = stream->Read(buffer, size); 761 if (ret >= B_OK) 762 return swap_data(B_INT16_TYPE, buffer, ret, B_SWAP_BENDIAN_TO_HOST); 763 return ret; 764 } 765 766 // _ReadRLE16 767 // 768 // reads 16-bit RLE data into provided buffer 769 // 770 // row pointer to buffer for one row 771 // numPixels number of pixels that fit into row buffer 772 ssize_t 773 SGIImage::_ReadRLE16(uint16* row, int32 numPixels) const 774 { 775 int32 ch; // current character 776 uint32 count; // RLE count 777 uint32 length = 0; // number of bytes read... 778 779 uint32 bufferSize = 1024; 780 int16* buffer = new int16[bufferSize]; 781 uint32 bufferPos = bufferSize; 782 status_t ret = B_OK; 783 784 while (numPixels > 0) { 785 786 // fetch another buffer if we need to 787 if (bufferPos >= bufferSize) { 788 ret = read_and_swap(fStream, buffer, bufferSize * 2); 789 if (ret < B_OK) 790 break; 791 bufferPos = 0; 792 } 793 794 ch = buffer[bufferPos ++]; 795 length ++; 796 797 count = ch & 127; 798 if (count == 0) 799 break; 800 801 if (ch & 128) { 802 for (uint32 i = 0; i < count; i++) { 803 804 // fetch another buffer if we need to 805 if (bufferPos >= bufferSize) { 806 ret = read_and_swap(fStream, buffer, bufferSize * 2); 807 if (ret < B_OK) { 808 delete[] buffer; 809 return ret; 810 } else 811 bufferPos = 0; 812 } 813 814 *row = B_HOST_TO_BENDIAN_INT16(buffer[bufferPos ++]); 815 row++; 816 numPixels--; 817 length++; 818 } 819 } else { 820 821 // fetch another buffer if we need to 822 if (bufferPos >= bufferSize) { 823 ret = read_and_swap(fStream, buffer, bufferSize * 2); 824 if (ret < B_OK) { 825 delete[] buffer; 826 return ret; 827 } else 828 bufferPos = 0; 829 } 830 831 ch = B_HOST_TO_BENDIAN_INT16(buffer[bufferPos ++]); 832 length ++; 833 for (uint32 i = 0; i < count; i++) { 834 *row = ch; 835 row++; 836 numPixels--; 837 } 838 } 839 } 840 delete[] buffer; 841 return (numPixels > 0 ? ret : length * 2); 842 } 843 844 // _ReadRLE16 845 // 846 // reads 16-bit RLE data into provided buffer 847 // 848 // row pointer to buffer for one row 849 // numPixels number of pixels that fit into row buffer 850 ssize_t 851 SGIImage::_ReadRLE16(uint16* row, uint16* rleBuffer, int32 numPixels) const 852 { 853 int32 ch; // current character 854 uint32 count; // RLE count 855 uint32 length = 0; // number of bytes read... 856 857 if (numPixels <= 0) 858 return B_ERROR; 859 860 while (numPixels > 0) { 861 862 ch = *rleBuffer ++; 863 length ++; 864 865 count = ch & 127; 866 if (count == 0) 867 break; 868 869 if (ch & 128) { 870 for (uint32 i = 0; i < count; i++) { 871 872 *row = B_HOST_TO_BENDIAN_INT16(*rleBuffer ++); 873 row++; 874 numPixels--; 875 length++; 876 } 877 } else { 878 879 ch = B_HOST_TO_BENDIAN_INT16(*rleBuffer ++); 880 length ++; 881 for (uint32 i = 0; i < count; i++) { 882 *row = ch; 883 row++; 884 numPixels--; 885 } 886 } 887 } 888 return length * 2; 889 } 890 891 // _WriteRLE8 892 // 893 // writes 8-bit RLE data into the stream 894 // 895 // row pointer to buffer for one row 896 // numPixels number of pixels that fit into row buffer 897 ssize_t 898 SGIImage::_WriteRLE8(uint8* row, int32 numPixels) const 899 { 900 int32 length = 0; // length of output line 901 int32 count; // number of repeated/non-repeated pixels 902 int32 i; // looping var 903 uint8* start; // start of sequence 904 uint16 repeat; // repeated pixel 905 906 907 for (int32 x = numPixels; x > 0;) { 908 start = row; 909 row += 2; 910 x -= 2; 911 912 while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) { 913 row++; 914 x--; 915 } 916 917 row -= 2; 918 x += 2; 919 920 count = row - start; 921 while (count > 0) { 922 i = count > 126 ? 126 : count; 923 count -= i; 924 925 if (_WriteChar(128 | i) == EOF) 926 return EOF; 927 length ++; 928 929 while (i > 0) { 930 if (_WriteChar(*start) == EOF) 931 return EOF; 932 start ++; 933 i --; 934 length ++; 935 } 936 } 937 938 if (x <= 0) 939 break; 940 941 start = row; 942 repeat = row[0]; 943 944 row ++; 945 x --; 946 947 while (x > 0 && *row == repeat) { 948 row ++; 949 x --; 950 } 951 952 count = row - start; 953 while (count > 0) { 954 i = count > 126 ? 126 : count; 955 count -= i; 956 957 if (_WriteChar(i) == EOF) 958 return EOF; 959 length ++; 960 961 if (_WriteChar(repeat) == EOF) 962 return (-1); 963 length ++; 964 } 965 } 966 967 length ++; 968 969 if (_WriteChar(0) == EOF) 970 return EOF; 971 else 972 return length; 973 } 974 975 976 // _WriteRLE16 977 // 978 // writes 16-bit RLE data into the stream 979 // 980 // row pointer to buffer for one row 981 // numPixels number of pixels that fit into row buffer 982 ssize_t 983 SGIImage::_WriteRLE16(uint16* row, int32 numPixels) const 984 { 985 int32 length = 0; // length of output line 986 int32 count; // number of repeated/non-repeated pixels 987 int32 i; // looping var 988 int32 x; // looping var 989 uint16* start; // start of sequence 990 uint16 repeat; // repeated pixel 991 992 993 for (x = numPixels; x > 0;) { 994 start = row; 995 row += 2; 996 x -= 2; 997 998 while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) { 999 row ++; 1000 x --; 1001 } 1002 1003 row -= 2; 1004 x += 2; 1005 1006 count = row - start; 1007 while (count > 0) { 1008 i = count > 126 ? 126 : count; 1009 count -= i; 1010 1011 if (_WriteShort(128 | i) == EOF) 1012 return EOF; 1013 length ++; 1014 1015 while (i > 0) { 1016 if (_WriteShort(*start) == EOF) 1017 return EOF; 1018 start ++; 1019 i --; 1020 length ++; 1021 } 1022 } 1023 1024 if (x <= 0) 1025 break; 1026 1027 start = row; 1028 repeat = row[0]; 1029 1030 row ++; 1031 x --; 1032 1033 while (x > 0 && *row == repeat) { 1034 row ++; 1035 x --; 1036 } 1037 1038 count = row - start; 1039 while (count > 0) { 1040 i = count > 126 ? 126 : count; 1041 count -= i; 1042 1043 if (_WriteShort(i) == EOF) 1044 return EOF; 1045 length ++; 1046 1047 if (_WriteShort(repeat) == EOF) 1048 return EOF; 1049 length ++; 1050 } 1051 } 1052 1053 length ++; 1054 1055 if (_WriteShort(0) == EOF) 1056 return EOF; 1057 else 1058 return (2 * length); 1059 } 1060 1061 1062