1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 #include <Aspect_GenericColorMap.hxx>
20 #include <Image_PseudoColorImage.hxx>
22 #include <AlienImage_MemoryOperations.hxx>
23 #include <AlienImage_SUNRFFormat.hxx>
24 #include <Image_Convertor.hxx>
25 #include <AlienImage_SunRFAlienData.ixx>
26 #include <Aspect_ColorMapEntry.hxx>
28 #include <Standard_Byte.hxx>
29 #include <Standard.hxx>
32 static int Verbose = 1 ;
37 // Each line of the image is rounded out to a multiple of 16 bits
38 #define ROWBYTES() (((myHeader.ras_width*myHeader.ras_depth + 7 )/8 + 1 ) & ~1 )
42 AlienImage_SunRFAlienData::AlienImage_SunRFAlienData()
46 void AlienImage_SunRFAlienData::SetFormat(
47 const AlienImage_SUNRFFormat aFormat )
49 { switch ( aFormat ) {
50 case AlienImage_SUNRF_Old :
51 myHeader.ras_type = RT_OLD ; break ;
52 case AlienImage_SUNRF_Standard :
53 myHeader.ras_type = RT_STANDARD ; break ;
54 case AlienImage_SUNRF_ByteEncoded :
55 myHeader.ras_type = RT_BYTE_ENCODED ; break ;
56 case AlienImage_SUNRF_RGB :
57 myHeader.ras_type = RT_FORMAT_RGB ; break ;
59 cout << "SunRFAlienData : Unknown or Unsuported Format\n" ;
64 AlienImage_SUNRFFormat AlienImage_SunRFAlienData::Format() const
66 { AlienImage_SUNRFFormat ret = AlienImage_SUNRF_Unknown ;
68 switch ( myHeader.ras_type ) {
70 ret = AlienImage_SUNRF_Old ; break ;
72 ret = AlienImage_SUNRF_Standard ; break ;
73 case RT_BYTE_ENCODED :
74 ret = AlienImage_SUNRF_ByteEncoded ; break ;
76 ret = AlienImage_SUNRF_RGB ; break ;
83 void AlienImage_SunRFAlienData::FreeData()
86 if ( myData && myDataSize ) {
87 //Free all allocated memory
88 Standard::Free(myData) ;
93 if ( myRedData && myHeader.ras_maplength ) {
94 //Free all allocated memory
95 Standard::Free( myRedData) ;
99 if ( myGreenData && myHeader.ras_maplength ) {
100 //Free all allocated memory
101 Standard::Free(myGreenData) ;
105 if ( myBlueData && myHeader.ras_maplength ) {
106 //Free all allocated memory
107 Standard::Free(myBlueData) ;
113 void AlienImage_SunRFAlienData::Clear()
118 myHeader.ras_magic = RAS_MAGIC ;
119 myHeader.ras_width = 0 ;
120 myHeader.ras_height = 0 ;
121 myHeader.ras_length = 0 ;
122 myHeader.ras_type = RT_STANDARD ;
123 myHeader.ras_maptype = RMT_NONE ;
124 myHeader.ras_maplength = 0 ;
128 Standard_Boolean AlienImage_SunRFAlienData::Write( OSD_File& file ) const
130 { Standard_Integer size;
131 AlienImage_SUNRFFileHeader TheHeader = myHeader ;
133 // Write out TheHeader information
135 if ( myData && myDataSize &&
136 myHeader.ras_type == RT_FORMAT_RGB &&
137 myHeader.ras_depth == 8 ) {
138 // Convert PseudoColorImage to TrueColor
140 Handle(Image_Image) aImage = ToImage() ;
142 if ( aImage->IsKind( STANDARD_TYPE(Image_PseudoColorImage) ) ) {
143 Image_Convertor Convertor;
145 Handle(Image_ColorImage) aCImage =
146 Convertor.Convert(Handle(Image_PseudoColorImage)::DownCast(aImage));
148 Handle(AlienImage_SunRFAlienData) newThis =
149 new AlienImage_SunRFAlienData() ;
151 newThis->FromImage( aCImage ) ;
152 newThis->SetFormat( AlienImage_SUNRF_RGB ) ;
153 return newThis->Write( file ) ;
157 size = ( Standard_Integer ) sizeof( TheHeader ) ;
159 const Standard_Address pHeader = ( Standard_Address ) &TheHeader ;
161 file.Write( pHeader, sizeof( TheHeader ) ) ;
163 if ( file.Failed() ) {
165 file.Seek( 0, OSD_FromBeginning ) ;
166 return( Standard_False ) ;
169 // write out the color map buffer
171 if ( TheHeader.ras_maplength ) {
172 file.Write( myRedData, myHeader.ras_maplength/3 ) ;
173 file.Write( myGreenData, myHeader.ras_maplength/3 ) ;
174 file.Write( myBlueData, myHeader.ras_maplength/3 ) ;
176 if ( file.Failed() ) {
178 file.Seek( 0, OSD_FromBeginning ) ;
179 return( Standard_False ) ;
183 Standard_Integer rwbytes ;
185 rwbytes = ROWBYTES() ;
187 if ( myData && myDataSize ) {
188 if ( myHeader.ras_type == RT_OLD ||
189 myHeader.ras_type == RT_STANDARD ||
190 myHeader.ras_type == RT_FORMAT_RGB ) {
191 if ( myHeader.ras_type == RT_FORMAT_RGB ) {
192 // Swap Sun Default BGR Format to RGB
193 Standard_Byte *p = ( Standard_Byte * )myData ;
194 Standard_Byte tmp, *pix ;
195 Standard_Integer j, i ;
197 if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) {
198 for ( i = 0 ;i < myHeader.ras_height ; i++, p += rwbytes ) {
199 for ( j = 0, pix=p; j < myHeader.ras_width ; j++,pix+=3) {
200 if ( myHeader.ras_depth == 32 ) pix++ ;
207 else if ( myHeader.ras_depth == 8 ) {
209 file.Seek( 0, OSD_FromBeginning ) ;
210 return( Standard_False ) ;
214 file.Write( myData, myDataSize ) ;
216 if ( file.Failed() ) {
218 file.Seek( 0, OSD_FromBeginning ) ;
219 return( Standard_False ) ;
222 if ( myHeader.ras_type == RT_FORMAT_RGB &&
223 ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) ) {
224 // Swap RGB Format to Sun Default
225 Standard_Byte *p = ( Standard_Byte * )myData ;
226 Standard_Byte tmp, *pix ;
227 Standard_Integer j, i ;
229 for ( i = 0 ;i < myHeader.ras_height ; i++, p += rwbytes ) {
230 for ( j = 0, pix=p; j < myHeader.ras_width ; j++,pix+=3) {
231 if ( myHeader.ras_depth == 32 ) pix++ ;
239 else if ( myHeader.ras_type == RT_BYTE_ENCODED ) {
240 Standard_Byte *p = ( Standard_Byte * )myData ;
243 for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) {
244 if ( WritePixelRow( file, ( Standard_Address) p, rwbytes ) ==
246 file.Seek( 0, OSD_FromBeginning ) ;
247 return( Standard_False ) ;
255 return( Standard_True ) ;
260 Standard_Boolean AlienImage_SunRFAlienData::Read( OSD_File& file )
262 { Standard_Integer bblcount, size ;
263 Standard_Address pheader = ( Standard_Address ) &myHeader ;
265 // Read in myHeader information
267 file.Read( pheader, sizeof( myHeader ), bblcount ) ;
269 if ( file.Failed() || ( bblcount != sizeof( myHeader ) ) ) {
271 file.Seek( 0, OSD_FromBeginning ) ;
272 return( Standard_False ) ;
275 // check to see if the dump file is in the proper format */
276 if (myHeader.ras_magic != RAS_MAGIC) {
277 // ERROR "XWD file format version mismatch."
279 file.Seek( 0, OSD_FromBeginning ) ;
280 return( Standard_False ) ;
284 if ( Verbose ) cout << myHeader << endl << flush ;
287 // read in the color map buffer
289 if ( myHeader.ras_maplength ) {
290 size = myHeader.ras_maplength / 3 ;
292 myRedData = Standard::Allocate( size ) ;
293 myGreenData = Standard::Allocate( size ) ;
294 myBlueData = Standard::Allocate( size ) ;
296 file.Read( myRedData, size, bblcount ) ;
297 file.Read( myGreenData, size, bblcount ) ;
298 file.Read( myBlueData, size, bblcount ) ;
300 if ( file.Failed() || ( bblcount != size ) ) {
302 file.Seek( 0, OSD_FromBeginning ) ;
303 return( Standard_False ) ;
308 Standard_Byte *r = ( Standard_Byte * )myRedData ;
309 Standard_Byte *g = ( Standard_Byte * )myGreenData ;
310 Standard_Byte *b = ( Standard_Byte * )myBlueData ;
312 for (i = 0 ; i < myHeader.ncolors; i++,p++) {
313 cout << "(" << r << "," << g << "," << b << ")\n" << flush ;
320 if ( myHeader.ras_width && myHeader.ras_height && myHeader.ras_depth ) {
321 Standard_Integer rwbytes ;
323 rwbytes = ROWBYTES() ;
325 myDataSize = rwbytes * myHeader.ras_height ;
327 myData = Standard::Allocate( myDataSize ) ;
329 if ( myHeader.ras_type == RT_OLD ||
330 myHeader.ras_type == RT_STANDARD ||
331 myHeader.ras_type == RT_FORMAT_RGB ) {
332 file.Read( myData, myDataSize, bblcount ) ;
334 if ( file.Failed() || ( bblcount != myDataSize ) ) {
336 file.Seek( 0, OSD_FromBeginning ) ;
337 return( Standard_False ) ;
340 if ( myHeader.ras_type == RT_FORMAT_RGB &&
341 ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 )) {
342 // Swap RGB to Sun Default BGR Format
343 Standard_Byte *p = ( Standard_Byte * )myData ;
344 Standard_Byte tmp, *pix ;
345 Standard_Integer i, j ;
347 for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) {
348 for ( j = 0, pix = p; j < myHeader.ras_width ; j++,pix+=3) {
349 if ( myHeader.ras_depth == 32 ) pix++ ;
357 else if ( myHeader.ras_type == RT_BYTE_ENCODED ) {
358 Standard_Byte *p = ( Standard_Byte * )myData ;
361 for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) {
362 if ( ReadPixelRow( file, ( Standard_Address) p, rwbytes ) ==
364 file.Seek( 0, OSD_FromBeginning ) ;
365 return( Standard_False ) ;
372 return( Standard_True ) ;
376 Handle_Image_Image AlienImage_SunRFAlienData::ToImage() const
378 { if ( myHeader.ras_depth <= 8 &&
379 myHeader.ras_maplength ) {
380 return( ToPseudoColorImage() ) ;
382 else if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) {
383 return( ToColorImage() ) ;
386 Standard_TypeMismatch_Raise_if( Standard_True,
387 "Attempt to convert a SunRFAlienData to a unknown Image_Image type");
393 void AlienImage_SunRFAlienData::FromImage( const Handle_Image_Image& anImage )
395 { if ( anImage->Type() == Image_TOI_PseudoColorImage ) {
396 Handle(Image_PseudoColorImage) aPImage =
397 Handle(Image_PseudoColorImage)::DownCast(anImage) ;
399 FromPseudoColorImage( aPImage ) ;
401 else if ( anImage->Type() == Image_TOI_ColorImage ) {
402 Handle(Image_ColorImage) aCImage =
403 Handle(Image_ColorImage)::DownCast(anImage) ;
405 FromColorImage( aCImage ) ;
408 Standard_TypeMismatch_Raise_if( Standard_True,
409 "Attempt to convert a unknown Image_Image type to a SunRFAlienData");
413 //------------------------------------------------------------------------------
415 //------------------------------------------------------------------------------
417 Standard_Boolean AlienImage_SunRFAlienData::ReadPixelRow(
419 const Standard_Address pdata,
420 const Standard_Integer rwbytes)
422 { Standard_Byte *p = ( Standard_Byte * )pdata ;
423 Standard_Byte byte, val ;
424 Standard_Integer RLEcnt, PixelCount, i, bblcount ;
425 Standard_Address pb = ( Standard_Address ) &byte ;
429 while ( PixelCount < myHeader.ras_width ) {
430 file.Read( pb, 1, bblcount ) ;
432 if ( file.Failed() || ( bblcount != 1 ) ) {
434 file.Seek( 0, OSD_FromBeginning ) ;
435 return( Standard_False ) ;
438 if ( byte != RUN_FLAG ) {
439 // Get a single pixel byte
440 RLEcnt = 1 , val = byte ;
443 file.Read( pb, 1, bblcount ) ;
445 if ( file.Failed() || ( bblcount != 1 ) ) {
447 file.Seek( 0, OSD_FromBeginning ) ;
448 return( Standard_False ) ;
452 RLEcnt = 1 , val = RUN_FLAG ;
457 file.Read( pb, 1, bblcount ) ;
459 if ( file.Failed() || ( bblcount != 1 ) ) {
461 file.Seek( 0, OSD_FromBeginning ) ;
462 return( Standard_False ) ;
468 for ( i = 0 ; i < RLEcnt ; i++, PixelCount++, p++ ) *p = val ;
472 return( Standard_True ) ;
476 Standard_Boolean AlienImage_SunRFAlienData::WritePixelRow(
478 const Standard_Address pdata,
479 const Standard_Integer rwbytes ) const
480 { Standard_Integer n, n1, n2 = 0;
481 Standard_Byte *scanln = ( Standard_Byte * ) pdata ;
484 while ( n2 < rwbytes ) {
488 while( ( n2 < rwbytes ) && ( scanln[n1] == scanln[n2] ) ) n2++ ;
493 b = scanln[n1]; file.Write( ( Standard_Address ) &b, 1 ) ;
495 if ( scanln[n1] == RUN_FLAG ) {
496 b = 0 ; file.Write( ( Standard_Address ) &b, 1 ) ;
499 if ( file.Failed() ) {
501 file.Seek( 0, OSD_FromBeginning ) ;
502 return( Standard_False ) ;
508 b = RUN_FLAG ; file.Write( ( Standard_Address ) &b, 1) ;
509 b = 255 ; file.Write( ( Standard_Address ) &b, 1) ;
510 b = scanln[n1];file.Write( ( Standard_Address ) &b, 1) ;
513 if ( file.Failed() ) {
515 file.Seek( 0, OSD_FromBeginning ) ;
516 return( Standard_False ) ;
520 b = RUN_FLAG ; file.Write( ( Standard_Address ) &b, 1 ) ;
521 b = n-1 ; file.Write( ( Standard_Address ) &b, 1 ) ;
522 b = scanln[n1];file.Write( ( Standard_Address ) &b, 1 ) ;
527 return( Standard_True ) ;
531 void AlienImage_SunRFAlienData::FromPseudoColorImage(
532 const Handle(Image_PseudoColorImage)& TheImage)
534 { Standard_Integer rowbytes,i ;
535 Standard_Integer x, y, pix;
536 Handle(Image_PseudoColorImage)anImage =
537 TheImage->Squeeze(Aspect_IndexPixel( 0 )) ;
538 Handle(Aspect_ColorMap) Cmap = anImage->ColorMap() ;
539 Aspect_ColorMapEntry aEntry ;
542 myHeader.ras_magic = RAS_MAGIC ;
543 myHeader.ras_width = anImage->Width() ;
544 myHeader.ras_height = anImage->Height() ;
545 myHeader.ras_depth = 8 ;
547 rowbytes = ROWBYTES() ;
549 myDataSize = myHeader.ras_height * rowbytes ;
550 myData = Standard::Allocate( myDataSize ) ;
551 myHeader.ras_length = myDataSize ;
553 myHeader.ras_maptype = RMT_EQUAL_RGB ;
554 myHeader.ras_maplength = Cmap->Size() ;
556 myRedData = Standard::Allocate( myHeader.ras_maplength ) ;
557 myGreenData = Standard::Allocate( myHeader.ras_maplength ) ;
558 myBlueData = Standard::Allocate( myHeader.ras_maplength ) ;
560 Standard_Byte *pr = ( Standard_Byte * ) myRedData ;
561 Standard_Byte *pg = ( Standard_Byte * ) myGreenData ;
562 Standard_Byte *pb = ( Standard_Byte * ) myBlueData ;
564 for ( i = 0 ; i < myHeader.ras_maplength ; i++, pr++, pg++, pb++ ) {
565 aEntry = Cmap->FindEntry( i ) ;
566 *pr = ( Standard_Byte ) ( aEntry.Color().Red() * 255. + 0.5 ) ;
567 *pg = ( Standard_Byte ) ( aEntry.Color().Green() * 255. + 0.5 ) ;
568 *pb = ( Standard_Byte ) ( aEntry.Color().Blue() * 255. + 0.5 ) ;
571 myHeader.ras_maplength *= 3 ;
573 if ( myData != NULL ) {
574 Standard_Byte *pr = ( Standard_Byte * ) myData ;
577 for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) {
578 for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) {
580 pix = anImage->Pixel( anImage->LowerX()+x ,
581 anImage->LowerY()+y ).Value() ;
583 *p = ( Standard_Byte ) pix ; p++ ;
589 void AlienImage_SunRFAlienData::FromColorImage(
590 const Handle_Image_ColorImage& anImage)
592 { Standard_Integer rowbytes ;
593 Standard_Integer x, y;
595 Standard_Real r,g,b ;
599 myHeader.ras_magic = RAS_MAGIC ;
600 myHeader.ras_width = anImage->Width() ;
601 myHeader.ras_height = anImage->Height() ;
602 myHeader.ras_depth = 24 ;
604 rowbytes = ROWBYTES() ;
606 myDataSize = myHeader.ras_height * rowbytes ;
607 myData = Standard::Allocate( myDataSize ) ;
608 myHeader.ras_length = myDataSize ;
610 myHeader.ras_maptype = RMT_NONE ;
611 myHeader.ras_maplength = 0 ;
613 if ( myData != NULL ) {
614 Standard_Byte *pr = ( Standard_Byte * ) myData ;
617 for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) {
618 for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) {
620 col = anImage->Pixel( anImage->LowerX()+x ,
621 anImage->LowerY()+y ).Value() ;
623 r = ( Standard_Integer ) ( col.Red() * 255. + 0.5 );
624 g = ( Standard_Integer ) ( col.Green() * 255. + 0.5 );
625 b = ( Standard_Integer ) ( col.Blue() * 255. + 0.5 );
627 *p = ( Standard_Byte ) b ; p++ ;
628 *p = ( Standard_Byte ) g ; p++ ;
629 *p = ( Standard_Byte ) r ; p++ ;
635 Handle_Image_ColorImage AlienImage_SunRFAlienData::ToColorImage() const
637 { Aspect_ColorPixel CPixel ;
638 Quantity_Color acolor ;
639 Handle(Image_ColorImage) ret_image = NULL ;
640 Standard_Integer x,y, rowbytes ;
641 Standard_Real r,g,b ;
642 Standard_Byte *pr = ( Standard_Byte * ) myData ;
645 if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) {
646 ret_image = new Image_ColorImage( 0,0,
647 (Standard_Integer)myHeader.ras_width,
648 (Standard_Integer)myHeader.ras_height ) ;
650 rowbytes = ROWBYTES() ;
652 for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) {
653 for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) {
654 if ( myHeader.ras_depth == 32 ) p++ ; // Skeep Alpha
655 b = ( Standard_Real ) *p / 255. ; p++ ;
656 g = ( Standard_Real ) *p / 255. ; p++ ;
657 r = ( Standard_Real ) *p / 255. ; p++ ;
659 acolor.SetValues( r,g,b, Quantity_TOC_RGB ) ;
661 CPixel.SetValue ( acolor ) ;
663 ret_image->SetPixel( ret_image->LowerX()+x ,
664 ret_image->LowerY()+y, CPixel ) ;
670 return( ret_image ) ;
673 Handle_Image_PseudoColorImage AlienImage_SunRFAlienData::ToPseudoColorImage()
676 { Standard_Real r,g,b ;
677 Standard_Integer x, y ;
678 Handle(Image_PseudoColorImage) ret_image = NULL ;
680 if ( myHeader.ras_depth <= 8 &&
681 myHeader.ras_maplength ) {
682 Standard_Integer i,rowbytes ;
683 Aspect_ColorMapEntry Centry ;
684 Quantity_Color color ;
685 Aspect_IndexPixel IPixel ;
686 Standard_Byte *red = ( Standard_Byte * ) myRedData ;
687 Standard_Byte *green = ( Standard_Byte * ) myGreenData ;
688 Standard_Byte *blue = ( Standard_Byte * ) myBlueData ;
690 Standard_Byte *pr = ( Standard_Byte * ) myData ;
691 Handle(Aspect_GenericColorMap) colormap =
692 new Aspect_GenericColorMap();
694 for ( i = 0 ; i < myHeader.ras_maplength/3 ; i++, red++, green++, blue++ ) {
695 r = ( Standard_Real ) *red / 255. ;
696 g = ( Standard_Real ) *green / 255. ;
697 b = ( Standard_Real ) *blue / 255. ;
698 color.SetValues( r,g,b, Quantity_TOC_RGB );
699 Centry.SetValue( i, color ) ;
700 colormap->AddEntry( Centry ) ;
703 ret_image = new Image_PseudoColorImage( 0,0,
704 Standard_Integer(myHeader.ras_width),
705 Standard_Integer(myHeader.ras_height),
708 rowbytes = ROWBYTES() ;
710 for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) {
711 for ( x = 0, p = pr ; x < myHeader.ras_width ; x++, p++ ) {
713 IPixel.SetValue( Standard_Integer( *p ) ) ;
714 ret_image->SetPixel( ret_image->LowerX()+x ,
715 ret_image->LowerY()+y, IPixel ) ;