#include #include #include #include #include #include #include #include #include #ifdef TRACE static int Verbose = 1 ; #endif #define RUN_FLAG 0x80 // Each line of the image is rounded out to a multiple of 16 bits #define ROWBYTES() (((myHeader.ras_width*myHeader.ras_depth + 7 )/8 + 1 ) & ~1 ) AlienImage_SunRFAlienData::AlienImage_SunRFAlienData() { Clear() ; } void AlienImage_SunRFAlienData::SetFormat( const AlienImage_SUNRFFormat aFormat ) { switch ( aFormat ) { case AlienImage_SUNRF_Old : myHeader.ras_type = RT_OLD ; break ; case AlienImage_SUNRF_Standard : myHeader.ras_type = RT_STANDARD ; break ; case AlienImage_SUNRF_ByteEncoded : myHeader.ras_type = RT_BYTE_ENCODED ; break ; case AlienImage_SUNRF_RGB : myHeader.ras_type = RT_FORMAT_RGB ; break ; default : cout << "SunRFAlienData : Unknown or Unsuported Format\n" ; break ; } } AlienImage_SUNRFFormat AlienImage_SunRFAlienData::Format() const { AlienImage_SUNRFFormat ret = AlienImage_SUNRF_Unknown ; switch ( myHeader.ras_type ) { case RT_OLD : ret = AlienImage_SUNRF_Old ; break ; case RT_STANDARD : ret = AlienImage_SUNRF_Standard ; break ; case RT_BYTE_ENCODED : ret = AlienImage_SUNRF_ByteEncoded ; break ; case RT_FORMAT_RGB : ret = AlienImage_SUNRF_RGB ; break ; } return ret ; } void AlienImage_SunRFAlienData::FreeData() { if ( myData && myDataSize ) { //Free all allocated memory Standard::Free(myData) ; myData = NULL ; myDataSize = 0 ; } if ( myRedData && myHeader.ras_maplength ) { //Free all allocated memory Standard::Free( myRedData) ; myRedData = NULL ; } if ( myGreenData && myHeader.ras_maplength ) { //Free all allocated memory Standard::Free(myGreenData) ; myRedData = NULL ; } if ( myBlueData && myHeader.ras_maplength ) { //Free all allocated memory Standard::Free(myBlueData) ; myRedData = NULL ; } } void AlienImage_SunRFAlienData::Clear() { FreeData() ; myHeader.ras_magic = RAS_MAGIC ; myHeader.ras_width = 0 ; myHeader.ras_height = 0 ; myHeader.ras_length = 0 ; myHeader.ras_type = RT_STANDARD ; myHeader.ras_maptype = RMT_NONE ; myHeader.ras_maplength = 0 ; } Standard_Boolean AlienImage_SunRFAlienData::Write( OSD_File& file ) const { AlienImage_SUNRFFileHeader TheHeader = myHeader ; // Write out TheHeader information if ( myData && myDataSize && myHeader.ras_type == RT_FORMAT_RGB && myHeader.ras_depth == 8 ) { // Convert PseudoColorImage to TrueColor Handle(Image_Image) aImage = ToImage() ; if ( aImage->IsKind( STANDARD_TYPE(Image_PseudoColorImage) ) ) { Image_Convertor Convertor; Handle(Image_ColorImage) aCImage = Convertor.Convert(Handle(Image_PseudoColorImage)::DownCast(aImage)); Handle(AlienImage_SunRFAlienData) newThis = new AlienImage_SunRFAlienData() ; newThis->FromImage( aCImage ) ; newThis->SetFormat( AlienImage_SUNRF_RGB ) ; return newThis->Write( file ) ; } } const Standard_Address pHeader = ( Standard_Address ) &TheHeader ; file.Write( pHeader, sizeof( TheHeader ) ) ; if ( file.Failed() ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } // write out the color map buffer if ( TheHeader.ras_maplength ) { file.Write( myRedData, myHeader.ras_maplength/3 ) ; file.Write( myGreenData, myHeader.ras_maplength/3 ) ; file.Write( myBlueData, myHeader.ras_maplength/3 ) ; if ( file.Failed() ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } Standard_Integer rwbytes ; rwbytes = ROWBYTES() ; if ( myData && myDataSize ) { if ( myHeader.ras_type == RT_OLD || myHeader.ras_type == RT_STANDARD || myHeader.ras_type == RT_FORMAT_RGB ) { if ( myHeader.ras_type == RT_FORMAT_RGB ) { // Swap Sun Default BGR Format to RGB Standard_Byte *p = ( Standard_Byte * )myData ; Standard_Byte tmp, *pix ; Standard_Integer j, i ; if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) { for ( i = 0 ;i < myHeader.ras_height ; i++, p += rwbytes ) { for ( j = 0, pix=p; j < myHeader.ras_width ; j++,pix+=3) { if ( myHeader.ras_depth == 32 ) pix++ ; tmp = *pix ; *pix = *(pix+2) ; *(pix+2) = tmp ; } } } else if ( myHeader.ras_depth == 8 ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } file.Write( myData, myDataSize ) ; if ( file.Failed() ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } if ( myHeader.ras_type == RT_FORMAT_RGB && ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) ) { // Swap RGB Format to Sun Default Standard_Byte *p = ( Standard_Byte * )myData ; Standard_Byte tmp, *pix ; Standard_Integer j, i ; for ( i = 0 ;i < myHeader.ras_height ; i++, p += rwbytes ) { for ( j = 0, pix=p; j < myHeader.ras_width ; j++,pix+=3) { if ( myHeader.ras_depth == 32 ) pix++ ; tmp = *pix ; *pix = *(pix+2) ; *(pix+2) = tmp ; } } } } else if ( myHeader.ras_type == RT_BYTE_ENCODED ) { Standard_Byte *p = ( Standard_Byte * )myData ; Standard_Integer i ; for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) { if ( WritePixelRow( file, ( Standard_Address) p, rwbytes ) == Standard_False ) { file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } } } return( Standard_True ) ; } Standard_Boolean AlienImage_SunRFAlienData::Read( OSD_File& file ) { Standard_Integer bblcount, size ; Standard_Address pheader = ( Standard_Address ) &myHeader ; // Read in myHeader information file.Read( pheader, sizeof( myHeader ), bblcount ) ; if ( file.Failed() || ( bblcount != sizeof( myHeader ) ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } // check to see if the dump file is in the proper format */ if (myHeader.ras_magic != RAS_MAGIC) { // ERROR "XWD file format version mismatch." file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } #ifdef TRACE if ( Verbose ) cout << myHeader << endl << flush ; #endif // read in the color map buffer if ( myHeader.ras_maplength ) { size = myHeader.ras_maplength / 3 ; myRedData = Standard::Allocate( size ) ; myGreenData = Standard::Allocate( size ) ; myBlueData = Standard::Allocate( size ) ; file.Read( myRedData, size, bblcount ) ; file.Read( myGreenData, size, bblcount ) ; file.Read( myBlueData, size, bblcount ) ; if ( file.Failed() || ( bblcount != size ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } #ifdef TRACE if ( Verbose ) { Standard_Byte *r = ( Standard_Byte * )myRedData ; Standard_Byte *g = ( Standard_Byte * )myGreenData ; Standard_Byte *b = ( Standard_Byte * )myBlueData ; for (i = 0 ; i < myHeader.ncolors; i++,p++) { cout << "(" << r << "," << g << "," << b << ")\n" << flush ; } } #endif } if ( myHeader.ras_width && myHeader.ras_height && myHeader.ras_depth ) { Standard_Integer rwbytes ; rwbytes = ROWBYTES() ; myDataSize = rwbytes * myHeader.ras_height ; myData = Standard::Allocate( myDataSize ) ; if ( myHeader.ras_type == RT_OLD || myHeader.ras_type == RT_STANDARD || myHeader.ras_type == RT_FORMAT_RGB ) { file.Read( myData, myDataSize, bblcount ) ; if ( file.Failed() || ( bblcount != myDataSize ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } if ( myHeader.ras_type == RT_FORMAT_RGB && ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 )) { // Swap RGB to Sun Default BGR Format Standard_Byte *p = ( Standard_Byte * )myData ; Standard_Byte tmp, *pix ; Standard_Integer i, j ; for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) { for ( j = 0, pix = p; j < myHeader.ras_width ; j++,pix+=3) { if ( myHeader.ras_depth == 32 ) pix++ ; tmp = *pix ; *pix = *(pix+2) ; *(pix+2) = tmp ; } } } } else if ( myHeader.ras_type == RT_BYTE_ENCODED ) { Standard_Byte *p = ( Standard_Byte * )myData ; Standard_Integer i ; for ( i = 0 ; i < myHeader.ras_height ; i++, p += rwbytes ) { if ( ReadPixelRow( file, ( Standard_Address) p, rwbytes ) == Standard_False ) { file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } } } return( Standard_True ) ; } Handle_Image_Image AlienImage_SunRFAlienData::ToImage() const { if ( myHeader.ras_depth <= 8 && myHeader.ras_maplength ) { return( ToPseudoColorImage() ) ; } else if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) { return( ToColorImage() ) ; } else { Standard_TypeMismatch_Raise_if( Standard_True, "Attempt to convert a SunRFAlienData to a unknown Image_Image type"); return( NULL ) ; } } void AlienImage_SunRFAlienData::FromImage( const Handle_Image_Image& anImage ) { if ( anImage->Type() == Image_TOI_PseudoColorImage ) { Handle(Image_PseudoColorImage) aPImage = Handle(Image_PseudoColorImage)::DownCast(anImage) ; FromPseudoColorImage( aPImage ) ; } else if ( anImage->Type() == Image_TOI_ColorImage ) { Handle(Image_ColorImage) aCImage = Handle(Image_ColorImage)::DownCast(anImage) ; FromColorImage( aCImage ) ; } else { Standard_TypeMismatch_Raise_if( Standard_True, "Attempt to convert a unknown Image_Image type to a SunRFAlienData"); } } //------------------------------------------------------------------------------ // Private Method //------------------------------------------------------------------------------ Standard_Boolean AlienImage_SunRFAlienData::ReadPixelRow( OSD_File& file, const Standard_Address pdata, const Standard_Integer rwbytes) { Standard_Byte *p = ( Standard_Byte * )pdata ; Standard_Byte byte, val ; Standard_Integer RLEcnt, PixelCount, i, bblcount ; Standard_Address pb = ( Standard_Address ) &byte ; PixelCount = 0 ; while ( PixelCount < myHeader.ras_width ) { file.Read( pb, 1, bblcount ) ; if ( file.Failed() || ( bblcount != 1 ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } if ( byte != RUN_FLAG ) { // Get a single pixel byte RLEcnt = 1 , val = byte ; } else { // RLE Flag file.Read( pb, 1, bblcount ) ; if ( file.Failed() || ( bblcount != 1 ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } if ( byte == 0 ) { RLEcnt = 1 , val = RUN_FLAG ; } else { RLEcnt = byte ; file.Read( pb, 1, bblcount ) ; if ( file.Failed() || ( bblcount != 1 ) ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } val = byte ; } for ( i = 0 ; i < RLEcnt ; i++, PixelCount++, p++ ) *p = val ; } } return( Standard_True ) ; } Standard_Boolean AlienImage_SunRFAlienData::WritePixelRow( OSD_File& file, const Standard_Address pdata, const Standard_Integer rwbytes ) const { Standard_Integer n, n1, n2 = 0; Standard_Byte *scanln = ( Standard_Byte * ) pdata ; Standard_Byte b ; while ( n2 < rwbytes ) { n1 = n2 ; n2 = n1 + 1 ; while( ( n2 < rwbytes ) && ( scanln[n1] == scanln[n2] ) ) n2++ ; n = n2 - n1 ; if ( n == 1 ) { b = scanln[n1]; file.Write( ( Standard_Address ) &b, 1 ) ; if ( scanln[n1] == RUN_FLAG ) { b = 0 ; file.Write( ( Standard_Address ) &b, 1 ) ; } if ( file.Failed() ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } else { while ( n > 256 ) { b = RUN_FLAG ; file.Write( ( Standard_Address ) &b, 1) ; b = 255 ; file.Write( ( Standard_Address ) &b, 1) ; b = scanln[n1];file.Write( ( Standard_Address ) &b, 1) ; n -= 256 ; if ( file.Failed() ) { // ERROR file.Seek( 0, OSD_FromBeginning ) ; return( Standard_False ) ; } } b = RUN_FLAG ; file.Write( ( Standard_Address ) &b, 1 ) ; b = Standard_Byte(n-1) ; file.Write( ( Standard_Address ) &b, 1 ) ; b = scanln[n1];file.Write( ( Standard_Address ) &b, 1 ) ; } } return( Standard_True ) ; } void AlienImage_SunRFAlienData::FromPseudoColorImage( const Handle(Image_PseudoColorImage)& TheImage) { Standard_Integer rowbytes,i ; Standard_Integer x, y, pix; Handle(Image_PseudoColorImage)anImage = TheImage->Squeeze(Aspect_IndexPixel( 0 )) ; Handle(Aspect_ColorMap) Cmap = anImage->ColorMap() ; Aspect_ColorMapEntry aEntry ; FreeData() ; myHeader.ras_magic = RAS_MAGIC ; myHeader.ras_width = anImage->Width() ; myHeader.ras_height = anImage->Height() ; myHeader.ras_depth = 8 ; rowbytes = ROWBYTES() ; myDataSize = myHeader.ras_height * rowbytes ; myData = Standard::Allocate( myDataSize ) ; myHeader.ras_length = myDataSize ; myHeader.ras_maptype = RMT_EQUAL_RGB ; myHeader.ras_maplength = Cmap->Size() ; myRedData = Standard::Allocate( myHeader.ras_maplength ) ; myGreenData = Standard::Allocate( myHeader.ras_maplength ) ; myBlueData = Standard::Allocate( myHeader.ras_maplength ) ; Standard_Byte *pr = ( Standard_Byte * ) myRedData ; Standard_Byte *pg = ( Standard_Byte * ) myGreenData ; Standard_Byte *pb = ( Standard_Byte * ) myBlueData ; for ( i = 0 ; i < myHeader.ras_maplength ; i++, pr++, pg++, pb++ ) { aEntry = Cmap->FindEntry( i ) ; *pr = ( Standard_Byte ) ( aEntry.Color().Red() * 255. + 0.5 ) ; *pg = ( Standard_Byte ) ( aEntry.Color().Green() * 255. + 0.5 ) ; *pb = ( Standard_Byte ) ( aEntry.Color().Blue() * 255. + 0.5 ) ; } myHeader.ras_maplength *= 3 ; if ( myData != NULL ) { Standard_Byte *pr = ( Standard_Byte * ) myData ; Standard_Byte *p ; for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) { for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) { pix = anImage->Pixel( anImage->LowerX()+x , anImage->LowerY()+y ).Value() ; *p = ( Standard_Byte ) pix ; p++ ; } } } } void AlienImage_SunRFAlienData::FromColorImage( const Handle_Image_ColorImage& anImage) { Standard_Integer rowbytes ; Standard_Integer x, y; Quantity_Color col ; Standard_Real r,g,b ; FreeData() ; myHeader.ras_magic = RAS_MAGIC ; myHeader.ras_width = anImage->Width() ; myHeader.ras_height = anImage->Height() ; myHeader.ras_depth = 24 ; rowbytes = ROWBYTES() ; myDataSize = myHeader.ras_height * rowbytes ; myData = Standard::Allocate( myDataSize ) ; myHeader.ras_length = myDataSize ; myHeader.ras_maptype = RMT_NONE ; myHeader.ras_maplength = 0 ; if ( myData != NULL ) { Standard_Byte *pr = ( Standard_Byte * ) myData ; Standard_Byte *p ; for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) { for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) { col = anImage->Pixel( anImage->LowerX()+x , anImage->LowerY()+y ).Value() ; r = ( Standard_Integer ) ( col.Red() * 255. + 0.5 ); g = ( Standard_Integer ) ( col.Green() * 255. + 0.5 ); b = ( Standard_Integer ) ( col.Blue() * 255. + 0.5 ); *p = ( Standard_Byte ) b ; p++ ; *p = ( Standard_Byte ) g ; p++ ; *p = ( Standard_Byte ) r ; p++ ; } } } } Handle_Image_ColorImage AlienImage_SunRFAlienData::ToColorImage() const { Aspect_ColorPixel CPixel ; Quantity_Color acolor ; Handle(Image_ColorImage) ret_image = NULL ; Standard_Integer x,y, rowbytes ; Standard_Real r,g,b ; Standard_Byte *pr = ( Standard_Byte * ) myData ; Standard_Byte *p ; if ( myHeader.ras_depth == 24 || myHeader.ras_depth == 32 ) { ret_image = new Image_ColorImage( 0,0, (Standard_Integer)myHeader.ras_width, (Standard_Integer)myHeader.ras_height ) ; rowbytes = ROWBYTES() ; for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) { for ( x = 0, p = pr ; x < myHeader.ras_width ; x++ ) { if ( myHeader.ras_depth == 32 ) p++ ; // Skeep Alpha b = ( Standard_Real ) *p / 255. ; p++ ; g = ( Standard_Real ) *p / 255. ; p++ ; r = ( Standard_Real ) *p / 255. ; p++ ; acolor.SetValues( r,g,b, Quantity_TOC_RGB ) ; CPixel.SetValue ( acolor ) ; ret_image->SetPixel( ret_image->LowerX()+x , ret_image->LowerY()+y, CPixel ) ; } } } return( ret_image ) ; } Handle_Image_PseudoColorImage AlienImage_SunRFAlienData::ToPseudoColorImage() const { Standard_Real r,g,b ; Standard_Integer x, y ; Handle(Image_PseudoColorImage) ret_image = NULL ; if ( myHeader.ras_depth <= 8 && myHeader.ras_maplength ) { Standard_Integer i,rowbytes ; Aspect_ColorMapEntry Centry ; Quantity_Color color ; Aspect_IndexPixel IPixel ; Standard_Byte *red = ( Standard_Byte * ) myRedData ; Standard_Byte *green = ( Standard_Byte * ) myGreenData ; Standard_Byte *blue = ( Standard_Byte * ) myBlueData ; Standard_Byte *p ; Standard_Byte *pr = ( Standard_Byte * ) myData ; Handle(Aspect_GenericColorMap) colormap = new Aspect_GenericColorMap(); for ( i = 0 ; i < myHeader.ras_maplength/3 ; i++, red++, green++, blue++ ) { r = ( Standard_Real ) *red / 255. ; g = ( Standard_Real ) *green / 255. ; b = ( Standard_Real ) *blue / 255. ; color.SetValues( r,g,b, Quantity_TOC_RGB ); Centry.SetValue( i, color ) ; colormap->AddEntry( Centry ) ; } ret_image = new Image_PseudoColorImage( 0,0, Standard_Integer(myHeader.ras_width), Standard_Integer(myHeader.ras_height), colormap ) ; rowbytes = ROWBYTES() ; for ( y = 0 ; y < myHeader.ras_height ; y++, pr += rowbytes ) { for ( x = 0, p = pr ; x < myHeader.ras_width ; x++, p++ ) { IPixel.SetValue( Standard_Integer( *p ) ) ; ret_image->SetPixel( ret_image->LowerX()+x , ret_image->LowerY()+y, IPixel ) ; } } } return ret_image ; }