// encode public static byte[] Encode(libsecondlife.Image image, bool lossless) { if ( (image.Channels & ImageChannels.Color) == 0 || ((image.Channels & ImageChannels.Bump) != 0 && (image.Channels & ImageChannels.Alpha) == 0)) throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination"); MarshalledImage marshalled = new MarshalledImage(); // allocate and copy to input buffer marshalled.width = image.Width; marshalled.height = image.Height; marshalled.components = 3; if ((image.Channels & ImageChannels.Alpha) != 0) marshalled.components++; if ((image.Channels & ImageChannels.Bump) != 0) marshalled.components++; if (!LibslAllocDecoded(ref marshalled)) throw new Exception("LibslAllocDecoded failed"); int n = image.Width * image.Height; if ((image.Channels & ImageChannels.Color) != 0) { Marshal.Copy(image.Red, 0, marshalled.decoded, n); Marshal.Copy(image.Green, 0, (IntPtr)(marshalled.decoded.ToInt64() + n), n); Marshal.Copy(image.Blue, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 2), n); } if ((image.Channels & ImageChannels.Alpha) != 0) Marshal.Copy(image.Alpha, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 3), n); if ((image.Channels & ImageChannels.Bump) != 0) Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n); // codec will allocate output buffer if (!LibslEncode(ref marshalled, lossless)) throw new Exception("LibslEncode failed"); // copy output buffer byte[] encoded = new byte[marshalled.length]; Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length); // free buffers LibslFree(ref marshalled); return encoded; }
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="layerInfo"></param> /// <param name="components"></param> /// <returns></returns> public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] layerInfo, out int components) { bool success = false; layerInfo = null; components = 0; MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; DotNetAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Run the decode if (DotNetDecodeWithInfo(ref marshalled)) { components = marshalled.components; // Sanity check if (marshalled.layers * marshalled.resolutions * marshalled.components == marshalled.packet_count) { // Manually marshal the array of opj_packet_info structs MarshalledPacket[] packets = new MarshalledPacket[marshalled.packet_count]; int offset = 0; for (int i = 0; i < marshalled.packet_count; i++) { MarshalledPacket packet; packet.start_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_ph_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; // Skip the distortion field. WARNING: It looks like there is alignment // padding in here as well, this needs to be tested on different platforms offset += 12; packets[i] = packet; } layerInfo = new J2KLayerInfo[marshalled.layers]; for (int i = 0; i < marshalled.layers; i++) { int packetsPerLayer = marshalled.packet_count / marshalled.layers; MarshalledPacket startPacket = packets[packetsPerLayer * i]; MarshalledPacket endPacket = packets[(packetsPerLayer * (i + 1)) - 1]; layerInfo[i].Start = startPacket.start_pos; layerInfo[i].End = endPacket.end_pos; } success = true; } else { Logger.Log(String.Format( "Packet count mismatch in JPEG2000 stream. layers={0} resolutions={1} components={2} packets={3}", marshalled.layers, marshalled.resolutions, marshalled.components, marshalled.packet_count), Helpers.LogLevel.Warning); } } DotNetFree(ref marshalled); return success; }
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="layerInfo"></param> /// <param name="components"></param> /// <returns></returns> public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] layerInfo, out int components) { bool success = false; layerInfo = null; components = 0; MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; lock (OpenJPEGLock) { if (IntPtr.Size == 8) { DotNetAllocEncoded64(ref marshalled); } else { DotNetAllocEncoded(ref marshalled); } Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Run the decode bool decodeSuccess = (IntPtr.Size == 8) ? DotNetDecodeWithInfo64(ref marshalled) : DotNetDecodeWithInfo(ref marshalled); if (decodeSuccess) { components = marshalled.components; // Sanity check if (marshalled.layers * marshalled.resolutions * marshalled.components == marshalled.packet_count) { // Manually marshal the array of opj_packet_info structs MarshalledPacket[] packets = new MarshalledPacket[marshalled.packet_count]; int offset = 0; for (int i = 0; i < marshalled.packet_count; i++) { MarshalledPacket packet; packet.start_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_ph_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; //double distortion = (double)Marshal.ReadInt64(marshalled.packets, offset); offset += 8; packets[i] = packet; } layerInfo = new J2KLayerInfo[marshalled.layers]; for (int i = 0; i < marshalled.layers; i++) { int packetsPerLayer = marshalled.packet_count / marshalled.layers; MarshalledPacket startPacket = packets[packetsPerLayer * i]; MarshalledPacket endPacket = packets[(packetsPerLayer * (i + 1)) - 1]; layerInfo[i].Start = startPacket.start_pos; layerInfo[i].End = endPacket.end_pos; } // More sanity checking if (layerInfo.Length == 0 || layerInfo[layerInfo.Length - 1].End <= encoded.Length - 1) { success = true; for (int i = 0; i < layerInfo.Length; i++) { if (layerInfo[i].Start >= layerInfo[i].End || (i > 0 && layerInfo[i].Start <= layerInfo[i - 1].End)) { System.Text.StringBuilder output = new System.Text.StringBuilder( "Inconsistent packet data in JPEG2000 stream:\n"); for (int j = 0; j < layerInfo.Length; j++) { output.AppendFormat("Layer {0}: Start: {1} End: {2}\n", j, layerInfo[j].Start, layerInfo[j].End); } Logger.DebugLog(output.ToString()); success = false; break; } } if (!success) { for (int i = 0; i < layerInfo.Length; i++) { if (i < layerInfo.Length - 1) { layerInfo[i].End = layerInfo[i + 1].Start - 1; } else { layerInfo[i].End = marshalled.length; } } Logger.DebugLog("Corrected JPEG2000 packet data"); success = true; for (int i = 0; i < layerInfo.Length; i++) { if (layerInfo[i].Start >= layerInfo[i].End || (i > 0 && layerInfo[i].Start <= layerInfo[i - 1].End)) { System.Text.StringBuilder output = new System.Text.StringBuilder( "Still inconsistent packet data in JPEG2000 stream, giving up:\n"); for (int j = 0; j < layerInfo.Length; j++) { output.AppendFormat("Layer {0}: Start: {1} End: {2}\n", j, layerInfo[j].Start, layerInfo[j].End); } Logger.DebugLog(output.ToString()); success = false; break; } } } } else { Logger.Log(String.Format( "Last packet end in JPEG2000 stream extends beyond the end of the file. filesize={0} layerend={1}", encoded.Length, layerInfo[layerInfo.Length - 1].End), Helpers.LogLevel.Warning); } } else { Logger.Log(String.Format( "Packet count mismatch in JPEG2000 stream. layers={0} resolutions={1} components={2} packets={3}", marshalled.layers, marshalled.resolutions, marshalled.components, marshalled.packet_count), Helpers.LogLevel.Warning); } } if (IntPtr.Size == 8) { DotNetFree64(ref marshalled); } else { DotNetFree(ref marshalled); } } return(success); }
private static extern bool LibslEncode(ref MarshalledImage image, bool lossless);
private static extern bool DotNetEncode64(ref MarshalledImage image, bool lossless);
/// <summary> /// Encode a <seealso cref="ManagedImage"/> object into a byte array /// </summary> /// <param name="image">The <seealso cref="ManagedImage"/> object to encode</param> /// <param name="lossless">true to enable lossless conversion, only useful for small images ie: sculptmaps</param> /// <returns>A byte array containing the encoded Image object</returns> public static byte[] Encode(ManagedImage image, bool lossless) { if ((image.Channels & ManagedImage.ImageChannels.Color) == 0 || ((image.Channels & ManagedImage.ImageChannels.Bump) != 0 && (image.Channels & ManagedImage.ImageChannels.Alpha) == 0)) { throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination"); } byte[] encoded = null; MarshalledImage marshalled = new MarshalledImage(); // allocate and copy to input buffer marshalled.width = image.Width; marshalled.height = image.Height; marshalled.components = 3; if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) { marshalled.components++; } if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) { marshalled.components++; } lock (OpenJPEGLock) { bool allocSuccess = (IntPtr.Size == 8) ? DotNetAllocDecoded64(ref marshalled) : DotNetAllocDecoded(ref marshalled); if (!allocSuccess) { throw new Exception("DotNetAllocDecoded failed"); } int n = image.Width * image.Height; if ((image.Channels & ManagedImage.ImageChannels.Color) != 0) { Marshal.Copy(image.Red, 0, marshalled.decoded, n); Marshal.Copy(image.Green, 0, (IntPtr)(marshalled.decoded.ToInt64() + n), n); Marshal.Copy(image.Blue, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 2), n); } if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) { Marshal.Copy(image.Alpha, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 3), n); } if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) { Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n); } // codec will allocate output buffer bool encodeSuccess = (IntPtr.Size == 8) ? DotNetEncode64(ref marshalled, lossless) : DotNetEncode(ref marshalled, lossless); if (!encodeSuccess) { throw new Exception("DotNetEncode failed"); } // copy output buffer encoded = new byte[marshalled.length]; Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length); // free buffers if (IntPtr.Size == 8) { DotNetFree64(ref marshalled); } else { DotNetFree(ref marshalled); } } return(encoded); }
private static extern bool DotNetFree(ref MarshalledImage image);
private static extern bool DotNetAllocDecoded64(ref MarshalledImage image);
/// <summary> /// </summary> /// <param name = "encoded"></param> /// <param name = "managedImage"></param> /// <returns></returns> public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage) { MarshalledImage marshalled = new MarshalledImage {length = encoded.Length}; // Allocate and copy to input buffer lock (OpenJPEGLock) { if (IntPtr.Size == 8) DotNetAllocEncoded64(ref marshalled); else DotNetAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Codec will allocate output buffer if (IntPtr.Size == 8) DotNetDecode64(ref marshalled); else DotNetDecode(ref marshalled); int n = marshalled.width*marshalled.height; switch (marshalled.components) { case 1: // Grayscale managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); break; case 2: // Grayscale + alpha managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + n), managedImage.Alpha, 0, n); break; case 3: // RGB managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + n), managedImage.Green, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*2)), managedImage.Blue, 0, n); break; case 4: // RGBA managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + n), managedImage.Green, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*2)), managedImage.Blue, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*3)), managedImage.Alpha, 0, n); break; case 5: // RGBAB managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + n), managedImage.Green, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*2)), managedImage.Blue, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*3)), managedImage.Alpha, 0, n); Marshal.Copy((IntPtr) (marshalled.decoded.ToInt64() + (n*4)), managedImage.Bump, 0, n); break; default: Logger.Log("Decoded image with unhandled number of components: " + marshalled.components, Helpers.LogLevel.Error); if (IntPtr.Size == 8) DotNetFree64(ref marshalled); else DotNetFree(ref marshalled); managedImage = null; return false; } if (IntPtr.Size == 8) DotNetFree64(ref marshalled); else DotNetFree(ref marshalled); } return true; }
private static extern bool DotNetAllocDecoded(ref MarshalledImage image);
/// <summary> /// Encode a <seealso cref = "ManagedImage" /> object into a byte array /// </summary> /// <param name = "image">The <seealso cref = "ManagedImage" /> object to encode</param> /// <param name = "lossless">true to enable lossless conversion, only useful for small images ie: sculptmaps</param> /// <returns>A byte array containing the encoded Image object</returns> public static byte[] Encode(ManagedImage image, bool lossless) { if ((image.Channels & ManagedImage.ImageChannels.Color) == 0 || ((image.Channels & ManagedImage.ImageChannels.Bump) != 0 && (image.Channels & ManagedImage.ImageChannels.Alpha) == 0)) throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination"); byte[] encoded = null; MarshalledImage marshalled = new MarshalledImage {width = image.Width, height = image.Height, components = 3}; // allocate and copy to input buffer if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) marshalled.components++; if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) marshalled.components++; lock (OpenJPEGLock) { bool allocSuccess = (IntPtr.Size == 8) ? DotNetAllocDecoded64(ref marshalled) : DotNetAllocDecoded(ref marshalled); if (!allocSuccess) throw new Exception("DotNetAllocDecoded failed"); int n = image.Width*image.Height; if ((image.Channels & ManagedImage.ImageChannels.Color) != 0) { Marshal.Copy(image.Red, 0, marshalled.decoded, n); Marshal.Copy(image.Green, 0, (IntPtr) (marshalled.decoded.ToInt64() + n), n); Marshal.Copy(image.Blue, 0, (IntPtr) (marshalled.decoded.ToInt64() + n*2), n); } if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) Marshal.Copy(image.Alpha, 0, (IntPtr) (marshalled.decoded.ToInt64() + n*3), n); if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) Marshal.Copy(image.Bump, 0, (IntPtr) (marshalled.decoded.ToInt64() + n*4), n); // codec will allocate output buffer bool encodeSuccess = (IntPtr.Size == 8) ? DotNetEncode64(ref marshalled, lossless) : DotNetEncode(ref marshalled, lossless); if (!encodeSuccess) throw new Exception("DotNetEncode failed"); // copy output buffer encoded = new byte[marshalled.length]; Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length); // free buffers if (IntPtr.Size == 8) DotNetFree64(ref marshalled); else DotNetFree(ref marshalled); } return encoded; }
private static extern bool DotNetDecode64(ref MarshalledImage image);
private static extern bool DotNetEncode64(ref MarshalledImage image, bool lossless);
// encode public static byte[] Encode(libsecondlife.Image image, bool lossless) { if ( (image.Channels & ImageChannels.Color) == 0 || ((image.Channels & ImageChannels.Bump) != 0 && (image.Channels & ImageChannels.Alpha) == 0)) { throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination"); } MarshalledImage marshalled = new MarshalledImage(); // allocate and copy to input buffer marshalled.width = image.Width; marshalled.height = image.Height; marshalled.components = 3; if ((image.Channels & ImageChannels.Alpha) != 0) { marshalled.components++; } if ((image.Channels & ImageChannels.Bump) != 0) { marshalled.components++; } if (!LibslAllocDecoded(ref marshalled)) { throw new Exception("LibslAllocDecoded failed"); } int n = image.Width * image.Height; if ((image.Channels & ImageChannels.Color) != 0) { Marshal.Copy(image.Red, 0, marshalled.decoded, n); Marshal.Copy(image.Green, 0, (IntPtr)(marshalled.decoded.ToInt64() + n), n); Marshal.Copy(image.Blue, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 2), n); } if ((image.Channels & ImageChannels.Alpha) != 0) { Marshal.Copy(image.Alpha, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 3), n); } if ((image.Channels & ImageChannels.Bump) != 0) { Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n); } // codec will allocate output buffer if (!LibslEncode(ref marshalled, lossless)) { throw new Exception("LibslEncode failed"); } // copy output buffer byte[] encoded = new byte[marshalled.length]; Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length); // free buffers LibslFree(ref marshalled); return(encoded); }
private static extern bool DotNetDecodeWithInfo(ref MarshalledImage image);
private static extern bool DotNetDecode(ref MarshalledImage image);
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="layerInfo"></param> /// <param name="components"></param> /// <returns></returns> public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] layerInfo, out int components) { bool success = false; layerInfo = null; components = 0; MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; lock (OpenJPEGLock) { DotNetAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Run the decode if (DotNetDecodeWithInfo(ref marshalled)) { components = marshalled.components; // Sanity check if (marshalled.layers * marshalled.resolutions * marshalled.components == marshalled.packet_count) { // Manually marshal the array of opj_packet_info structs MarshalledPacket[] packets = new MarshalledPacket[marshalled.packet_count]; int offset = 0; for (int i = 0; i < marshalled.packet_count; i++) { MarshalledPacket packet; packet.start_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_ph_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; //double distortion = (double)Marshal.ReadInt64(marshalled.packets, offset); offset += 8; packets[i] = packet; } layerInfo = new J2KLayerInfo[marshalled.layers]; for (int i = 0; i < marshalled.layers; i++) { int packetsPerLayer = marshalled.packet_count / marshalled.layers; MarshalledPacket startPacket = packets[packetsPerLayer * i]; MarshalledPacket endPacket = packets[(packetsPerLayer * (i + 1)) - 1]; layerInfo[i].Start = startPacket.start_pos; layerInfo[i].End = endPacket.end_pos; } // More sanity checking if (layerInfo.Length == 0 || layerInfo[layerInfo.Length - 1].End <= encoded.Length - 1) { success = true; for (int i = 0; i < layerInfo.Length; i++) { if (layerInfo[i].Start >= layerInfo[i].End || (i > 0 && layerInfo[i].Start <= layerInfo[i - 1].End)) { System.Text.StringBuilder output = new System.Text.StringBuilder( "Inconsistent packet data in JPEG2000 stream:\n"); for (int j = 0; j < layerInfo.Length; j++) output.AppendFormat("Layer {0}: Start: {1} End: {2}\n", j, layerInfo[j].Start, layerInfo[j].End); Logger.Log(output.ToString(), Helpers.LogLevel.Error); success = false; break; } } } else { Logger.Log(String.Format( "Last packet end in JPEG2000 stream extends beyond the end of the file. filesize={0} layerend={1}", encoded.Length, layerInfo[layerInfo.Length - 1].End), Helpers.LogLevel.Warning); } } else { Logger.Log(String.Format( "Packet count mismatch in JPEG2000 stream. layers={0} resolutions={1} components={2} packets={3}", marshalled.layers, marshalled.resolutions, marshalled.components, marshalled.packet_count), Helpers.LogLevel.Warning); } } DotNetFree(ref marshalled); } return success; }
private static extern bool DotNetFree64(ref MarshalledImage image);
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="managedImage"></param> /// <returns></returns> public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage) { MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; LibslAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Codec will allocate output buffer LibslDecode(ref marshalled); int n = marshalled.width * marshalled.height; switch (marshalled.components) { case 1: // Grayscale managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); break; case 2: // Grayscale + alpha managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Alpha, 0, n); break; case 3: // RGB managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); break; case 4: // RGBA managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Alpha, 0, n); break; case 5: // RGBBA managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); // Bump comes before alpha in 5 channel encode Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Bump, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 4)), managedImage.Alpha, 0, n); break; default: Logger.Log("Decoded image with unhandled number of components: " + marshalled.components, Helpers.LogLevel.Error); LibslFree(ref marshalled); managedImage = null; return false; } LibslFree(ref marshalled); return true; }
private static extern bool DotNetDecodeWithInfo64(ref MarshalledImage image);
public static libsecondlife.Image Decode(byte[] encoded) { MarshalledImage marshalled = new MarshalledImage(); // allocate and copy to input buffer marshalled.length = encoded.Length; LibslAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // codec will allocate output buffer LibslDecode(ref marshalled); libsecondlife.Image image; int n = marshalled.width * marshalled.height; switch (marshalled.components) { case 1: // grayscale image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Array.Copy(image.Red, image.Green, n); Array.Copy(image.Red, image.Blue, n); break; case 2: // grayscale + alpha image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Array.Copy(image.Red, image.Green, n); Array.Copy(image.Red, image.Blue, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Alpha, 0, n); break; case 3: // RGB image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); break; case 4: // RGBA image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 3), image.Alpha, 0, n); break; case 5: // RGBBA image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha | ImageChannels.Bump); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 3), image.Bump, 0, n); // bump comes before alpha in 5 channel encode Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 4), image.Alpha, 0, n); break; default: throw new Exception("Decoded image with unhandled number of components (" + marshalled.components + ")"); } // free buffers LibslFree(ref marshalled); return(image); }
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="managedImage"></param> /// <returns></returns> public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage) { MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; lock (OpenJPEGLock) { if (IntPtr.Size == 8) { DotNetAllocEncoded64(ref marshalled); } else { DotNetAllocEncoded(ref marshalled); } Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Codec will allocate output buffer if (IntPtr.Size == 8) { DotNetDecode64(ref marshalled); } else { DotNetDecode(ref marshalled); } int n = marshalled.width * marshalled.height; switch (marshalled.components) { case 1: // Grayscale managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); break; case 2: // Grayscale + alpha managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n); Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Alpha, 0, n); break; case 3: // RGB managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); break; case 4: // RGBA managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Alpha, 0, n); break; case 5: // RGBAB managedImage = new ManagedImage(marshalled.width, marshalled.height, ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump); Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Alpha, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 4)), managedImage.Bump, 0, n); break; default: Logger.Log("Decoded image with unhandled number of components: " + marshalled.components, Helpers.LogLevel.Error); if (IntPtr.Size == 8) { DotNetFree64(ref marshalled); } else { DotNetFree(ref marshalled); } managedImage = null; return(false); } if (IntPtr.Size == 8) { DotNetFree64(ref marshalled); } else { DotNetFree(ref marshalled); } } return(true); }
private static extern bool LibslAllocDecoded(ref MarshalledImage image);
private static extern bool LibslAllocDecoded(ref MarshalledImage image);
private static extern bool LibslEncode(ref MarshalledImage image, bool lossless);
private static extern bool LibslDecode(ref MarshalledImage image);
private static extern bool LibslDecode(ref MarshalledImage image);
public static libsecondlife.Image Decode(byte[] encoded) { MarshalledImage marshalled = new MarshalledImage(); // allocate and copy to input buffer marshalled.length = encoded.Length; LibslAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // codec will allocate output buffer LibslDecode(ref marshalled); libsecondlife.Image image; int n = marshalled.width * marshalled.height; switch (marshalled.components) { case 1: // grayscale image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Array.Copy(image.Red, image.Green, n); Array.Copy(image.Red, image.Blue, n); break; case 2: // grayscale + alpha image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Array.Copy(image.Red, image.Green, n); Array.Copy(image.Red, image.Blue, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Alpha, 0, n); break; case 3: // RGB image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); break; case 4: // RGBA image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 3), image.Alpha, 0, n); break; case 5: // RGBBA image = new libsecondlife.Image(marshalled.width, marshalled.height, ImageChannels.Color | ImageChannels.Alpha | ImageChannels.Bump); Marshal.Copy(marshalled.decoded, image.Red, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n), image.Green, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 2), image.Blue, 0, n); Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 3), image.Bump, 0, n); // bump comes before alpha in 5 channel encode Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + n * 4), image.Alpha, 0, n); break; default: throw new Exception("Decoded image with unhandled number of components (" + marshalled.components + ")"); } // free buffers LibslFree(ref marshalled); return image; }
/// <summary> /// /// </summary> /// <param name="encoded"></param> /// <param name="layerInfo"></param> /// <param name="components"></param> /// <returns></returns> public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] layerInfo, out int components) { bool success = false; layerInfo = null; components = 0; MarshalledImage marshalled = new MarshalledImage(); // Allocate and copy to input buffer marshalled.length = encoded.Length; DotNetAllocEncoded(ref marshalled); Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length); // Run the decode if (DotNetDecodeWithInfo(ref marshalled)) { components = marshalled.components; // Sanity check if (marshalled.layers * marshalled.resolutions * marshalled.components == marshalled.packet_count) { // Manually marshal the array of opj_packet_info structs MarshalledPacket[] packets = new MarshalledPacket[marshalled.packet_count]; int offset = 0; for (int i = 0; i < marshalled.packet_count; i++) { MarshalledPacket packet; packet.start_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_ph_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; packet.end_pos = Marshal.ReadInt32(marshalled.packets, offset); offset += 4; // Skip the distortion field. WARNING: It looks like there is alignment // padding in here as well, this needs to be tested on different platforms offset += 12; packets[i] = packet; } layerInfo = new J2KLayerInfo[marshalled.layers]; for (int i = 0; i < marshalled.layers; i++) { int packetsPerLayer = marshalled.packet_count / marshalled.layers; MarshalledPacket startPacket = packets[packetsPerLayer * i]; MarshalledPacket endPacket = packets[(packetsPerLayer * (i + 1)) - 1]; layerInfo[i].Start = startPacket.start_pos; layerInfo[i].End = endPacket.end_pos; } success = true; } else { Logger.Log(String.Format( "Packet count mismatch in JPEG2000 stream. layers={0} resolutions={1} components={2} packets={3}", marshalled.layers, marshalled.resolutions, marshalled.components, marshalled.packet_count), Helpers.LogLevel.Warning); } } DotNetFree(ref marshalled); return(success); }