public byte[] Data() { byte[] data = new byte[FreeImage.GetHeight(_bitmap) * FreeImage.GetPitch(_bitmap)]; FreeImage.ConvertToRawBits(data, _bitmap, (int)FreeImage.GetPitch(_bitmap), FreeImage.GetBPP(_bitmap), FreeImage.GetRedMask(_bitmap), FreeImage.GetGreenMask(_bitmap), FreeImage.GetBlueMask(_bitmap), true); // need to swith red and blue bytes int stride = (int)(FreeImage.GetLine(_bitmap) / FreeImage.GetWidth(_bitmap)); for (int i = 0; i < FreeImage.GetHeight(_bitmap) * FreeImage.GetWidth(_bitmap); i += stride) { byte tmp = data[i]; data[i] = data[i + 2]; data[i + 2] = tmp; } if (ImageType == Graphics.ImageType.R8 || ImageType == Graphics.ImageType.RG8) { if (ImageType == Graphics.ImageType.R8) { data = data.Where((b, i) => i % stride == 0).ToArray(); } else { data = data.Where((b, i) => i % stride == 0 || i % stride == 1).ToArray(); } } // TODO: handle compressed textures. return(data); }
// Saving function protected override bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data) { SerialDib sdib; uint size = FreeImage.GetDIBSize(dib); // Store all data needed to recreate the bitmap sdib.width = FreeImage.GetWidth(dib); sdib.height = FreeImage.GetHeight(dib); sdib.pitch = (int)FreeImage.GetPitch(dib); sdib.bpp = FreeImage.GetBPP(dib); sdib.red_mask = FreeImage.GetRedMask(dib); sdib.green_mask = FreeImage.GetGreenMask(dib); sdib.blue_mask = FreeImage.GetBlueMask(dib); sdib.data = new byte[size]; // Copy the bitmaps data into the structures byte-array // The marshaller is used to create an IntPtr for using // 'ConvertToRawBits'. FreeImage.ConvertToRawBits(Marshal.UnsafeAddrOfPinnedArrayElement(sdib.data, 0), dib, sdib.pitch, sdib.bpp, sdib.red_mask, sdib.green_mask, sdib.blue_mask, false); // Use the healper function to write the header to the destination if (Write(io, handle, (uint)header.Length, 1, ref header) != 1) { return(false); } // Create a serializer BinaryFormatter formatter = new BinaryFormatter(); // Create a temporary stream MemoryStream stream = new MemoryStream(); // Create a compression stream GZipStream zipStream = new GZipStream(stream, CompressionMode.Compress); // Serialize the structure into the compression stream formatter.Serialize(zipStream, sdib); // Unload the compression stream zipStream.Dispose(); // Get the result data byte[] buffer = stream.GetBuffer(); // Use the healper function 'Write' to write the data to the destination if (Write(io, handle, 1, (uint)buffer.Length, ref buffer) != buffer.Length) { // Unload the temporary stream stream.Dispose(); return(false); } // Unload the temporary stream stream.Dispose(); return(true); }
public override object Process(FileInfo myInfo, string FilePath) { TextureComponent myTexture = new TextureComponent(); FileStream myStream = ReadFileStream(myInfo, FilePath); var Result2 = FreeImage.LoadFromStream(myStream); myTexture.Width = FreeImage.GetWidth(Result2); myTexture.Height = FreeImage.GetHeight(Result2); var Type = FreeImage.GetImageType(Result2); Debug.WriteLine("ImageType: " + Enum.GetName(typeof(FREE_IMAGE_TYPE), Type) + " was detected!"); FreeImage.ConvertToType(Result2, FREE_IMAGE_TYPE.FIT_BITMAP, true); // The bits per pixel and image type may have changed myTexture.bpp = FreeImage.GetBPP(Result2); myTexture.pitch = (int)FreeImage.GetPitch(Result2); myTexture.redMask = FreeImage.GetRedMask(Result2); myTexture.greenMask = FreeImage.GetGreenMask(Result2); myTexture.blueMask = FreeImage.GetBlueMask(Result2); myTexture.ImageBytes = new uint[(int)(myTexture.Width * myTexture.Height)]; // Create the byte array for the data var Data = new byte[(int)((myTexture.Width * myTexture.Height * myTexture.bpp - 1f) / 8) + 1]; //Converts the pixel data to bytes, do not try to use this call to switch the color channels because that only works for 16bpp bitmaps FreeImage.ConvertToRawBits(Data, Result2, myTexture.pitch, myTexture.bpp, myTexture.redMask, myTexture.greenMask, myTexture.blueMask, true); int Count = Vector <byte> .Count; float Iterator = Data.Length - (Data.Length % Count); Vector <byte> Work; int DestIterator = 0; for (int i = 0; i < Iterator; i += Count) { Work = new Vector <byte>(Data, i); var Result = Vector.AsVectorUInt32(Work); Result.CopyTo(myTexture.ImageBytes, DestIterator++); } //Array.Copy(Data, 0, myTexture.ImageBytes, 0, Data.Length); //FreeImage.FreeHbitmap(Result2); //TODO: FREE THE IMAGE OR LEAK myStream.Close(); return(myTexture); }
internal static BitmapContent Resize(this BitmapContent bitmap, int newWidth, int newHeight) { BitmapContent src = bitmap; SurfaceFormat format; src.TryGetFormat(out format); if (format != SurfaceFormat.Vector4) { var v4 = new PixelBitmapContent <Vector4>(src.Width, src.Height); BitmapContent.Copy(src, v4); src = v4; } // Convert to FreeImage bitmap var bytes = src.GetPixelData(); var fi = FreeImage.ConvertFromRawBits(bytes, FREE_IMAGE_TYPE.FIT_RGBAF, src.Width, src.Height, SurfaceFormat.Vector4.GetSize() * src.Width, 128, 0, 0, 0, true); // Resize var newfi = FreeImage.Rescale(fi, newWidth, newHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC); FreeImage.UnloadEx(ref fi); // Convert back to PixelBitmapContent<Vector4> src = new PixelBitmapContent <Vector4>(newWidth, newHeight); bytes = new byte[SurfaceFormat.Vector4.GetSize() * newWidth * newHeight]; FreeImage.ConvertToRawBits(bytes, newfi, SurfaceFormat.Vector4.GetSize() * newWidth, 128, 0, 0, 0, true); src.SetPixelData(bytes); FreeImage.UnloadEx(ref newfi); // Convert back to source type if required if (format != SurfaceFormat.Vector4) { var s = (BitmapContent)Activator.CreateInstance(bitmap.GetType(), new object[] { newWidth, newHeight }); BitmapContent.Copy(src, s); src = s; } return(src); }
/// <summary> /// Called by the XNA Framework when importing a texture file to be used as a game asset. This is the method called by the XNA Framework when an asset is to be imported into an object that can be recognized by the Content Pipeline. /// </summary> /// <param name="filename">Name of a game asset file.</param> /// <param name="context">Contains information for importing a game asset, such as a logger interface.</param> /// <returns>Resulting game asset.</returns> public override TextureContent Import(string filename, ContentImporterContext context) { var ext = Path.GetExtension(filename).ToLower(); // Special case for loading some formats switch (ext) { case ".dds": return(DdsLoader.Import(filename, context)); case ".bmp": return(LoadImage(filename)); } var output = new Texture2DContent { Identity = new ContentIdentity(filename) }; FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN; var fBitmap = FreeImage.LoadEx(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format); //if freeimage can not recognize the image type if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN) { throw new ContentLoadException("TextureImporter failed to load '" + filename + "'"); } //if freeimage can recognize the file headers but can't read its contents else if (fBitmap.IsNull) { throw new InvalidContentException("TextureImporter couldn't understand the contents of '" + filename + "'", output.Identity); } BitmapContent face = null; var height = (int)FreeImage.GetHeight(fBitmap); var width = (int)FreeImage.GetWidth(fBitmap); //uint bpp = FreeImage.GetBPP(fBitmap); var imageType = FreeImage.GetImageType(fBitmap); // Swizzle channels and expand to include an alpha channel fBitmap = ConvertAndSwapChannels(fBitmap, imageType); // The bits per pixel and image type may have changed uint bpp = FreeImage.GetBPP(fBitmap); imageType = FreeImage.GetImageType(fBitmap); var pitch = (int)FreeImage.GetPitch(fBitmap); var redMask = FreeImage.GetRedMask(fBitmap); var greenMask = FreeImage.GetGreenMask(fBitmap); var blueMask = FreeImage.GetBlueMask(fBitmap); // Create the byte array for the data byte[] bytes = new byte[((width * height * bpp - 1) / 8) + 1]; //Converts the pixel data to bytes, do not try to use this call to switch the color channels because that only works for 16bpp bitmaps FreeImage.ConvertToRawBits(bytes, fBitmap, pitch, bpp, redMask, greenMask, blueMask, true); // Create the Pixel bitmap content depending on the image type switch (imageType) { //case FREE_IMAGE_TYPE.FIT_BITMAP: default: face = new PixelBitmapContent <Color>(width, height); break; case FREE_IMAGE_TYPE.FIT_RGBA16: face = new PixelBitmapContent <Rgba64>(width, height); break; case FREE_IMAGE_TYPE.FIT_RGBAF: face = new PixelBitmapContent <Vector4>(width, height); break; } FreeImage.UnloadEx(ref fBitmap); face.SetPixelData(bytes); output.Faces[0].Add(face); return(output); }
//public Texture2D tex; public byte[] LoadImageBytes(string path, bool isLinear = false, bool isGrayscale = false, bool doMipMaps = false, bool forceGC = false, bool premultiplyAlpha = false) { // default bits per channel //uint origBPP = outBPP = 0; bool successfullyLoadedRaw = false; int width = 0, height = 0; TextureFormat formatToLoad = TextureFormat.ARGB32; RenderTextureFormat rtFormat = RenderTextureFormat.ARGB32; bool forceGrayscaleAfterTexture2D = false; var loadType = System.IO.Path.GetExtension(path); FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT; switch (loadType) { case ".png": loadFlags = FREE_IMAGE_LOAD_FLAGS.PNG_IGNOREGAMMA; break; case ".jpg": case ".jpeg": loadFlags = FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE; break; } // Format is stored in 'format' on successfull load. FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN; FIBITMAP dib; bool isModifiedEXR = false; char yChar = 'Y'; byte yByte = Convert.ToByte(yChar); char rChar = 'R'; byte rByte = Convert.ToByte(rChar); //byte[] byteArray = File.ReadAllBytes(path); FileStream stream = null; if (Path.GetExtension(path).ToLower() == ".exr") { stream = new FileStream(path, FileMode.Open); stream.Position = 66; isModifiedEXR = (stream.ReadByte() == rByte); if (isModifiedEXR) { Debug.Log("<color=blue>*** This is a modified EXR </color>"); //byteArray[66] = yByte; stream.Position = 66; stream.WriteByte(yByte); stream.Position = 0; } } #if UNITY_STANDALONE_OSX if (stream == null) { stream = new FileStream(path, FileMode.Open); } dib = FreeImage.LoadFromStream(stream, loadFlags, ref format); #else dib = FreeImage.LoadEx(path, loadFlags, ref format); Debug.Log("Used Heap Size After FreeImage.LoadEx: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); #endif if (stream != null) { stream.Dispose(); GC.Collect(); Debug.Log("Used Heap Size After stream.Dispose: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); } width = (int)FreeImageAPI.FreeImage.GetWidth(dib); height = (int)FreeImageAPI.FreeImage.GetHeight(dib); uint bpp = FreeImage.GetBPP(dib); int pitch = (int)FreeImage.GetPitch(dib); long byteSize = pitch * height; Debug.Log("width: " + width + ", height: " + height + ", bpp: " + bpp + ", pitch: " + pitch + "byteSize: " + byteSize); if (doMipMaps) { byteSize = (long)(byteSize * 1.6666f); } FreeImage.ConvertToRawBits(bytes, dib, pitch, bpp, 0, 0, 0, false); FreeImage.UnloadEx(ref dib); return(bytes); }
public RenderTexture LoadImage(string path, bool isLinear = false, bool isGrayscale = false, bool doMipMaps = false, bool forceGC = false, bool premultiplyAlpha = false) { // default bits per channel //uint origBPP = outBPP = 0; bool successfullyLoadedRaw = false; int width = 0, height = 0; TextureFormat formatToLoad = TextureFormat.ARGB32; RenderTextureFormat rtFormat = RenderTextureFormat.ARGB32; bool forceGrayscaleAfterTexture2D = false; //System.Threading.Thread newThread = new System.Threading.Thread(() => { var loadType = System.IO.Path.GetExtension(path); FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT; switch (loadType) { case ".png": loadFlags = FREE_IMAGE_LOAD_FLAGS.PNG_IGNOREGAMMA; break; case ".jpg": case ".jpeg": loadFlags = FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE; break; } // Format is stored in 'format' on successfull load. FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN; FIBITMAP dib; bool isModifiedEXR = false; char yChar = 'Y'; byte yByte = Convert.ToByte(yChar); char rChar = 'R'; byte rByte = Convert.ToByte(rChar); //byte[] byteArray = File.ReadAllBytes(path); FileStream stream = null; if (Path.GetExtension(path).ToLower() == ".exr") { stream = new FileStream(path, FileMode.Open); stream.Position = 66; isModifiedEXR = (stream.ReadByte() == rByte); if (isModifiedEXR) { Debug.Log("<color=blue>*** This is a modified EXR </color>"); //byteArray[66] = yByte; stream.Position = 66; stream.WriteByte(yByte); stream.Position = 0; } } #if UNITY_STANDALONE_OSX if (stream == null) { stream = new FileStream(path, FileMode.Open); } dib = FreeImage.LoadFromStream(stream, loadFlags, ref format); #else dib = FreeImage.LoadEx(path, loadFlags, ref format); Debug.Log("Used Heap Size After FreeImage.LoadEx: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); #endif if (stream != null) { stream.Dispose(); GC.Collect(); Debug.Log("Used Heap Size After stream.Dispose: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); } if (isModifiedEXR) { using (FileStream fs = new FileStream(path, FileMode.Open)) { fs.Position = 66; fs.WriteByte(rByte); fs.Position = 0; } } rtFormat = RenderTextureFormat.ARGB32; try { // Error handling if (dib.IsNull) { return(null); } FREE_IMAGE_TYPE origInputType = FreeImage.GetImageType(dib); //Debug.Log("DIB for :" + path); // read bits per channel of loaded image uint origBPP = FreeImage.GetBPP(dib); var header = FreeImage.GetInfoHeaderEx(dib); //Debug.Log("original BPP:" + origBPP); //Debug.Log("origInputType:" + origInputType); // check here if we need to convert single channel textures to RGB or vice versa based on source input texture type and destination type expected FREE_IMAGE_TYPE destType = FREE_IMAGE_TYPE.FIT_UNKNOWN; switch (origInputType) { case FREE_IMAGE_TYPE.FIT_UINT16: if (!isGrayscale) { destType = FREE_IMAGE_TYPE.FIT_RGBAF; } else { destType = FREE_IMAGE_TYPE.FIT_FLOAT; } break; case FREE_IMAGE_TYPE.FIT_RGBF: case FREE_IMAGE_TYPE.FIT_RGBAF: destType = isGrayscale ? FREE_IMAGE_TYPE.FIT_FLOAT : FREE_IMAGE_TYPE.FIT_RGBAF; break; case FREE_IMAGE_TYPE.FIT_RGB16: case FREE_IMAGE_TYPE.FIT_RGBA16: destType = isGrayscale ? FREE_IMAGE_TYPE.FIT_FLOAT : FREE_IMAGE_TYPE.FIT_RGBAF; break; case FREE_IMAGE_TYPE.FIT_BITMAP: if (isGrayscale) { if (Mathf.IsPowerOfTwo(header.biWidth) && Mathf.IsPowerOfTwo(header.biHeight)) { if (!premultiplyAlpha) { dib = FreeImage.ConvertToGreyscale(dib); } } else { //int w = Mathf.NextPowerOfTwo(header.biWidth); //int h = Mathf.NextPowerOfTwo(header.biHeight); //FIBITMAP bitmap2 = FreeImage.Allocate(w, h, 8); //FreeImage.Paste(bitmap2, dib, 0, 0, 255); //FreeImage.UnloadEx(ref dib); //dib = bitmap2; forceGrayscaleAfterTexture2D = true; dib = FreeImage.ConvertTo32Bits(dib); } } else { dib = FreeImage.ConvertTo32Bits(dib); } destType = FREE_IMAGE_TYPE.FIT_BITMAP; break; } //// premultiply if need be //if (premultiplyAlpha) // FreeImage.PreMultiplyWithAlpha(dib); // convert to destination expected type if (destType != FREE_IMAGE_TYPE.FIT_UNKNOWN && origInputType != destType) { Debug.Log("Trying to convert from:" + origInputType + ", to:" + destType); dib = FreeImage.ConvertToType(dib, destType, false); } //GC.Collect(); Debug.Log("Used Heap Size After FreeImage.ConvertToType: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); //if (isModifiedEXR && origInputType == FREE_IMAGE_TYPE.FIT_FLOAT) width = (int)FreeImageAPI.FreeImage.GetWidth(dib); height = (int)FreeImageAPI.FreeImage.GetHeight(dib); uint bpp = FreeImage.GetBPP(dib); int pitch = (int)FreeImage.GetPitch(dib); long byteSize = pitch * height; Debug.Log("byteSize: " + byteSize); FREE_IMAGE_TYPE inputType = FreeImage.GetImageType(dib); if (doMipMaps) { byteSize = (long)(byteSize * 1.6666f); } //bytes = new byte[byteSize]; FreeImage.ConvertToRawBits(bytes, dib, pitch, bpp, 0, 0, 0, false); Debug.Log("Used Heap Size After FreeImage.ConvertToRawBits: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); FreeImage.UnloadEx(ref dib); //GC.Collect(); //Debug.Log("Used Heap Size After FreeImage.UnloadEx: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); // choose texture format formatToLoad = TextureFormat.ARGB32; Debug.Log("inputType:" + inputType); switch (inputType) { case FREE_IMAGE_TYPE.FIT_FLOAT: formatToLoad = TextureFormat.RFloat; if (origInputType == FREE_IMAGE_TYPE.FIT_UINT16) { rtFormat = RenderTextureFormat.RHalf; } else { rtFormat = RenderTextureFormat.RFloat; } break; case FREE_IMAGE_TYPE.FIT_UINT16: formatToLoad = TextureFormat.RHalf; rtFormat = RenderTextureFormat.RHalf; break; case FREE_IMAGE_TYPE.FIT_RGBA16: formatToLoad = TextureFormat.RGBAHalf; rtFormat = RenderTextureFormat.ARGBHalf; isLinear = true; break; case FREE_IMAGE_TYPE.FIT_RGBAF: formatToLoad = TextureFormat.RGBAFloat; if (origInputType == FREE_IMAGE_TYPE.FIT_RGBA16 || origInputType == FREE_IMAGE_TYPE.FIT_RGB16) { rtFormat = RenderTextureFormat.ARGBHalf; } else { rtFormat = RenderTextureFormat.ARGBFloat; } isLinear = true; break; case FREE_IMAGE_TYPE.FIT_BITMAP: //Iterate over all scanlines switch (bpp) { case 8: { formatToLoad = TextureFormat.Alpha8; rtFormat = RenderTextureFormat.R8; } break; case 16: formatToLoad = TextureFormat.RGBA4444; rtFormat = RenderTextureFormat.ARGB4444; break; case 24: if (FreeImage.IsLittleEndian()) { int length = bytes.Length; // make sure it's a multiple of 3 int factor = length / 3; int adjustedLength = factor * 3; // convert back to RGB for (int i = 0; i < adjustedLength; i += 3) { // convert BGR to RGB var r = bytes[i]; bytes[i] = bytes[i + 2]; bytes[i + 2] = r; } } formatToLoad = TextureFormat.RGB24; rtFormat = RenderTextureFormat.ARGB32; break; case 32: if (forceGrayscaleAfterTexture2D) { formatToLoad = TextureFormat.ARGB32; rtFormat = RenderTextureFormat.R8; } else { if (FreeImage.IsLittleEndian()) { int length = bytes.Length; // make sure it's a multiple of 4 int factor = length / 4; int adjustedLength = factor * 4; for (int j = 0; j < adjustedLength; j += 4) { // convert BGRA to ARGB var a = bytes[j]; var r = bytes[j + 1]; bytes[j] = bytes[j + 3]; bytes[j + 1] = bytes[j + 2]; bytes[j + 2] = r; bytes[j + 3] = a; } } formatToLoad = TextureFormat.ARGB32; rtFormat = RenderTextureFormat.ARGB32; } break; } break; } successfullyLoadedRaw = true; } catch (System.Exception ex) { Debug.LogError("Exception: " + ex.Message); } } //); //newThread.IsBackground = true; //newThread.Start(); //newThread.Join(); //outBPP = origBPP; if (successfullyLoadedRaw) { RenderTexture temp = LoadRawToTexture2D(bytes, width, height, formatToLoad, rtFormat, doMipMaps, isLinear, forceGC, premultiplyAlpha); //GC.Collect(); Debug.Log("Used Heap Size After LoadRawToTexture2D: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); return(temp); } return(null); }