Reads and loads a Truevision TGA Format image file.
Inheritance: IDisposable
Example #1
0
        private unsafe void buttonConvertNew_Click( object sender, EventArgs _e )
        {
            if ( openFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;
            if ( saveFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;

            FileInfo	SourceFileName = new FileInfo( openFileDialog.FileName );
            FileInfo	TargetFileName = new FileInfo( saveFileDialog.FileName );

            int			W, H;
            float3[,]	Vectors;
            float		x, y, z;
            using ( TargaImage TGA = new TargaImage( SourceFileName.FullName, false ) )
            {
                // Convert
                byte[]		ImageContent = Bitmap.LoadBitmap( TGA.Image, out W, out H );
                Vectors = new float3[W,H];
                int		rha = 0;
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ )
                    {
                        x = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        y = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        z = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        rha++;	// Skip alpha

                        z = Math.Max( 0.0f, z );

                        float	Norm = 1.0f / (float) Math.Sqrt( x*x + y*y + z*z );
                        Vectors[X,Y].x = x * Norm;
                        Vectors[X,Y].y = y * Norm;
                        Vectors[X,Y].z = z * Norm;
                    }
            }

            // Convert to RG improved normal
            double	Nx, Ny;
            double	CosPhi, SinPhi, CosTheta, SinTheta, Normalizer;
            double	a = 1.0, b, c, d = 0.0, e, t;

            ushort[,]	PackedNormal = new ushort[W,H];
            for ( int Y=0; Y < H; Y++ )
                for ( int X=0; X < W; X++ )
                {
                    x = Vectors[X,Y].x;
                    y = Vectors[X,Y].y;
                    z = Vectors[X,Y].z;

                    CosTheta = z;
                    SinTheta = Math.Sqrt( 1 - z*z );
                    Normalizer = 1.0 / Math.Max( 1e-10, SinTheta );
                    CosPhi = x * Normalizer;
                    SinPhi = y * Normalizer;

                    e = SinTheta*SinTheta*SinTheta*SinTheta * CosPhi*CosPhi * SinPhi*SinPhi;
                    c = -SinTheta*SinTheta;
                    b = -CosTheta;

                    double[]	roots = Polynomial.solvePolynomial( a, b, c, d, e );

                    t = Math.Sqrt( 2.0 );
                    for ( int i=0; i < roots.Length; i++ )
                        if ( !double.IsNaN( roots[i] ) && roots[i] >= 0.0 )
                            t = Math.Min( t, roots[i] );

            // 					Nx = t * CosPhi * SinTheta;
            // 					Ny = t * SinPhi * SinTheta;
                    Nx = t * x;
                    Ny = t * y;

                    Vectors[X,Y].x = (float) (0.5 * (1.0 + Nx));
                    Vectors[X,Y].y = (float) (0.5 * (1.0 + Ny));
                    Vectors[X,Y].z = 0.0f;
                }

            // Save as target PNG
            using ( System.Drawing.Bitmap B = new System.Drawing.Bitmap( W, H, System.Drawing.Imaging.PixelFormat.Format32bppRgb ) )
            {
                System.Drawing.Imaging.BitmapData	LockedBitmap = B.LockBits( new System.Drawing.Rectangle( 0, 0, W, H ), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb );

                for ( int Y=0; Y < H; Y++ )
                {
                    byte*	pScanline = (byte*) LockedBitmap.Scan0 + LockedBitmap.Stride * Y;
                    for ( int X=0; X < W; X++ )
                    {
                        *pScanline++ = 0;
                        *pScanline++ = (byte) (255 * Vectors[X,Y].y);
                        *pScanline++ = (byte) (255 * Vectors[X,Y].x);
                        *pScanline++ = 0xFF;
                    }
                }

                B.UnlockBits( LockedBitmap );

                B.Save( TargetFileName.FullName );
            }
        }
Example #2
0
        /// <summary>
        /// Loads a Targa image file into a Bitmap object.
        /// </summary>
        /// <param name="sFileName">The Targa image filename</param>
        /// <returns>A Bitmap object with the Targa image loaded into it.</returns>
        public static System.Drawing.Bitmap LoadTargaImage(string sFileName)
        {
            System.Drawing.Bitmap b = null;
            using (TargaImage ti = new TargaImage(sFileName, false))
            {
                b = new System.Drawing.Bitmap(ti.Image);
            }

            return b;
        }
Example #3
0
        private unsafe void buttonConvertOld_Click( object sender, EventArgs args )
        {
            if ( openFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;
            if ( saveFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;

            FileInfo	SourceFileName = new FileInfo( openFileDialog.FileName );
            FileInfo	TargetFileName = new FileInfo( saveFileDialog.FileName );

            int			W, H;
            float3[,]	Vectors;
            float		x, y, z;
            using ( TargaImage TGA = new TargaImage( SourceFileName.FullName, false ) )
            {
                // Convert
                byte[]		ImageContent = Bitmap.LoadBitmap( TGA.Image, out W, out H );
                Vectors = new float3[W,H];
                int		rha = 0;
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ )
                    {
                        x = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        y = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        z = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        rha++;	// Skip alpha

                        z = Math.Max( 0.0f, z );

                        float	Norm = 1.0f / (float) Math.Sqrt( x*x + y*y + z*z );
                        Vectors[X,Y].x = x * Norm;
                        Vectors[X,Y].y = y * Norm;
                        Vectors[X,Y].z = z * Norm;
                    }
            }

            // Convert to RG slightly less improved normal
            double	Nx, Ny;
            double	a, b, c = -1.0, d, t;

            ushort[,]	PackedNormal = new ushort[W,H];
            for ( int Y=0; Y < H; Y++ )
                for ( int X=0; X < W; X++ )
                {
                    x = Vectors[X,Y].x;
                    y = Vectors[X,Y].y;
                    z = Vectors[X,Y].z;

                    // Here I'm using the exact algorithm described by http://rgba32.blogspot.fr/2011/02/improved-normal-map-distributions.html
                    a = (x * x) + (y * y);
                    b = z;
                    d = b*b - 4.0*a*c;
                    t = (-b + Math.Sqrt( d )) / (2.0 * a);

                    Nx = x * t;
                    Ny = y * t;

                    Vectors[X,Y].x = (float) (0.5 * (1.0 + Nx));
                    Vectors[X,Y].y = (float) (0.5 * (1.0 + Ny));
                    Vectors[X,Y].z = 0.0f;
                }

            // Save as target PNG
            using ( System.Drawing.Bitmap B = new System.Drawing.Bitmap( W, H, System.Drawing.Imaging.PixelFormat.Format32bppRgb ) )
            {
                System.Drawing.Imaging.BitmapData	LockedBitmap = B.LockBits( new System.Drawing.Rectangle( 0, 0, W, H ), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb );

                for ( int Y=0; Y < H; Y++ )
                {
                    byte*	pScanline = (byte*) LockedBitmap.Scan0 + LockedBitmap.Stride * Y;
                    for ( int X=0; X < W; X++ )
                    {
                        *pScanline++ = 0;
                        *pScanline++ = (byte) (255 * Vectors[X,Y].y);
                        *pScanline++ = (byte) (255 * Vectors[X,Y].x);
                        *pScanline++ = 0xFF;
                    }
                }

                B.UnlockBits( LockedBitmap );

                B.Save( TargetFileName.FullName );
            }
        }
Example #4
0
		public void	Load( byte[] _ImageFileContent, FILE_TYPE _FileType, ColorProfile _ProfileOverride )
		{
			m_Type = _FileType;
			try
			{
				switch ( _FileType )
				{
					case FILE_TYPE.JPEG:
					case FILE_TYPE.PNG:
					case FILE_TYPE.TIFF:
					case FILE_TYPE.GIF:
					case FILE_TYPE.BMP:
						using ( System.IO.MemoryStream Stream = new System.IO.MemoryStream( _ImageFileContent ) )
						{
							// ===== 1] Load the bitmap source =====
							BitmapDecoder	Decoder = BitmapDecoder.Create( Stream, BitmapCreateOptions.IgnoreColorProfile | BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnDemand );
							if ( Decoder.Frames.Count == 0 )
								throw new Exception( "BitmapDecoder failed to read at least one bitmap frame!" );

							BitmapFrame	Frame = Decoder.Frames[0];
							if ( Frame == null )
								throw new Exception( "Invalid decoded bitmap!" );

// DEBUG
// int		StrideX = (Frame.Format.BitsPerPixel>>3)*Frame.PixelWidth;
// byte[]	DebugImageSource = new byte[StrideX*Frame.PixelHeight];
// Frame.CopyPixels( DebugImageSource, StrideX, 0 );
// DEBUG

// pas de gamma sur les JPEG si non spécifié !
// Il y a bien une magouille faite lors de la conversion par le FormatConvertedBitmap!


							// ===== 2] Build the color profile =====
							m_ColorProfile = _ProfileOverride != null ? _ProfileOverride : new ColorProfile( Frame.Metadata as BitmapMetadata, _FileType );

							// ===== 3] Convert the frame to generic RGBA32F =====
							ConvertFrame( Frame );

							// ===== 4] Convert to CIE XYZ (our device-independent profile connection space) =====
							if ( ms_ReadContent && ms_ConvertContent2XYZ )
								m_ColorProfile.RGB2XYZ( m_Bitmap, m_Bitmap );
						}
						break;

					case FILE_TYPE.TGA:
						{
							// Load as a System.Drawing.Bitmap and convert to float4
							using ( System.IO.MemoryStream Stream = new System.IO.MemoryStream( _ImageFileContent ) )
								using ( TargaImage TGA = new TargaImage( Stream, !ms_ReadContent ) ) {
									// Create a default sRGB linear color profile
									m_ColorProfile = _ProfileOverride != null ? _ProfileOverride
										: new ColorProfile(
											ColorProfile.Chromaticities.sRGB,	// Use default sRGB color profile
											ColorProfile.GAMMA_CURVE.STANDARD,	// But with a standard gamma curve...
											TGA.ExtensionArea.GammaRatio		// ...whose gamma is retrieved from extension data
										);

									if ( ms_ReadContent ) {
										// Convert
										byte[]	ImageContent = LoadBitmap( TGA.Image, out m_Width, out m_Height );
										m_Bitmap = new float4[m_Width,m_Height];
										byte	A;
										int		i = 0;
										for ( int Y=0; Y < m_Height; Y++ )
											for ( int X=0; X < m_Width; X++ )
											{
												m_Bitmap[X,Y].x = BYTE_TO_FLOAT * ImageContent[i++];
												m_Bitmap[X,Y].y = BYTE_TO_FLOAT * ImageContent[i++];
												m_Bitmap[X,Y].z = BYTE_TO_FLOAT * ImageContent[i++];

												A = ImageContent[i++];
												m_bHasAlpha |= A != 0xFF;

												m_Bitmap[X,Y].w = BYTE_TO_FLOAT * A;
											}

										if ( ms_ConvertContent2XYZ ) {
											// Convert to CIEXYZ
											m_ColorProfile.RGB2XYZ( m_Bitmap, m_Bitmap );
										}
									} else {
										// Only read dimensions
										m_Width = TGA.Header.Width;
										m_Height = TGA.Header.Height;
									}
								}
							return;
						}

					case FILE_TYPE.HDR:
						{
							// Load as XYZ
							m_Bitmap = LoadAndDecodeHDRFormat( _ImageFileContent, true, _ProfileOverride, out m_ColorProfile );
							m_Width = m_Bitmap.GetLength( 0 );
							m_Height = m_Bitmap.GetLength( 1 );
							return;
						}

				#if USE_LIB_RAW
					case FILE_TYPE.CRW:
					case FILE_TYPE.CR2:
					case FILE_TYPE.DNG:
						{
							using ( System.IO.MemoryStream Stream = new System.IO.MemoryStream( _ImageFileContent ) )
								using ( LibRawManaged.RawFile Raw = new LibRawManaged.RawFile() ) {
									Raw.UnpackRAW( Stream );

									ColorProfile.Chromaticities	Chroma = Raw.ColorProfile == LibRawManaged.RawFile.COLOR_PROFILE.ADOBE_RGB
																		? ColorProfile.Chromaticities.AdobeRGB_D65	// Use Adobe RGB
																		: ColorProfile.Chromaticities.sRGB;			// Use default sRGB color profile

									// Create a default sRGB linear color profile
									m_ColorProfile = _ProfileOverride != null ? _ProfileOverride
										: new ColorProfile(
											Chroma,
											ColorProfile.GAMMA_CURVE.STANDARD,	// But with a standard gamma curve...
											1.0f								// Linear
										);

									// Also get back valid camera shot info
									m_bHasValidShotInfo = true;
									m_ISOSpeed = Raw.ISOSpeed;
									m_ShutterSpeed = Raw.ShutterSpeed;
									m_Aperture = Raw.Aperture;
									m_FocalLength = Raw.FocalLength;

 									// Convert
									m_Width = Raw.Width;
									m_Height = Raw.Height;
//									float	ColorNormalizer = 1.0f / Raw.Maximum;
									float	ColorNormalizer = 1.0f / 65535.0f;

									if ( ms_ReadContent ) {
										m_Bitmap = new float4[m_Width,m_Height];
										UInt16[,][]	ImageContent = Raw.Image;
										for ( int Y=0; Y < m_Height; Y++ )
											for ( int X=0; X < m_Width; X++ )
											{
 												m_Bitmap[X,Y].x = ImageContent[X,Y][0] * ColorNormalizer;
 												m_Bitmap[X,Y].y = ImageContent[X,Y][1] * ColorNormalizer;
 												m_Bitmap[X,Y].z = ImageContent[X,Y][2] * ColorNormalizer;
 												m_Bitmap[X,Y].w = ImageContent[X,Y][3] * ColorNormalizer;
 											}

										if ( ms_ConvertContent2XYZ ) {
											// Convert to CIEXYZ
											m_ColorProfile.RGB2XYZ( m_Bitmap, m_Bitmap );
										}
									}
								}

#region My poor attempt at reading CRW files
// 							using ( System.IO.MemoryStream Stream = new System.IO.MemoryStream( _ImageFileContent ) )
// 								using ( CanonRawLoader CRWLoader = new CanonRawLoader( Stream ) )
// 								{
// 									ColorProfile.Chromaticities	Chroma = CRWLoader.m_ColorProfile == CanonRawLoader.DataColorProfile.COLOR_PROFILE.ADOBE_RGB
// 																		? ColorProfile.Chromaticities.AdobeRGB_D65	// Use Adobe RGB
// 																		: ColorProfile.Chromaticities.sRGB;			// Use default sRGB color profile
// 
// 									// Create a default sRGB linear color profile
// 									m_ColorProfile = new ColorProfile(
// 											Chroma,
// 											ColorProfile.GAMMA_CURVE.STANDARD,	// But with a standard gamma curve...
// 											1.0f								// Linear
// 										);
// 
//  									// Convert
// 									m_Width = CRWLoader.m_RAWImage.m_Width;
// 									m_Height = CRWLoader.m_RAWImage.m_Height;
// 
// 									m_Bitmap = new float4[m_Width,m_Height];
// 									UInt16[]	ImageContent = CRWLoader.m_RAWImage.m_DecodedImage;
// 									int			i = 0;
// // 									for ( int Y=0; Y < m_Height; Y++ )
// // 										for ( int X=0; X < m_Width; X++ )
// // 										{
// //  											m_Bitmap[X,Y].x = ImageContent[i++] / 4096.0f;
// //  											m_Bitmap[X,Y].y = ImageContent[i++] / 4096.0f;
// //  											m_Bitmap[X,Y].z = ImageContent[i++] / 4096.0f;
// // 											i++;
// //  										}
// 
// 									i=0;
// 									for ( int Y=0; Y < m_Height; Y++ )
// 										for ( int X=0; X < m_Width; X++ )
//  											m_Bitmap[X,Y].x = ImageContent[i++] / 4096.0f;
// 									i=0;
// 									for ( int Y=0; Y < m_Height; Y++ )
// 										for ( int X=0; X < m_Width; X++ )
//  											m_Bitmap[X,Y].y = ImageContent[i++] / 4096.0f;
// 									i=0;
// 									for ( int Y=0; Y < m_Height; Y++ )
// 										for ( int X=0; X < m_Width; X++ )
//  											m_Bitmap[X,Y].z = ImageContent[i++] / 4096.0f;
// 
// 									// Convert to CIEXYZ
// 									m_ColorProfile.RGB2XYZ( m_Bitmap );
// 								}
#endregion
							return;
 						}
					#endif

					default:
						throw new NotSupportedException( "The image file type \"" + _FileType + "\" is not supported by the Bitmap class!" );
				}
			}
			catch ( Exception )
			{
				throw;	// Go on !
			}
		}