// // System.Drawing.Imaging.EncoderParameter.cs // // Author: // Ravindra (rkumar@novell.com) // Vladimir Vukicevic (vladimir@pobox.com) // // (C) 2004 Novell, Inc. http://www.novell.com // // // Copyright (C) 2004 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using System.Runtime.InteropServices; namespace System.Drawing.Imaging { [StructLayout(LayoutKind.Sequential)] public sealed class EncoderParameter : IDisposable { private Encoder encoder; private int valuesCount; private EncoderParameterValueType type; private IntPtr valuePtr; internal EncoderParameter () { } public EncoderParameter (Encoder encoder, byte value) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeByte; this.valuePtr = Marshal.AllocHGlobal (1); Marshal.WriteByte (this.valuePtr, value); } public EncoderParameter (Encoder encoder, byte[] value) { this.encoder = encoder; this.valuesCount = value.Length; this.type = EncoderParameterValueType.ValueTypeByte; this.valuePtr = Marshal.AllocHGlobal (1 * valuesCount); Marshal.Copy (value, 0, this.valuePtr, valuesCount); } public EncoderParameter (Encoder encoder, short value) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeShort; this.valuePtr = Marshal.AllocHGlobal (2); Marshal.WriteInt16 (this.valuePtr, value); } public EncoderParameter (Encoder encoder, short[] value) { this.encoder = encoder; this.valuesCount = value.Length; this.type = EncoderParameterValueType.ValueTypeShort; this.valuePtr = Marshal.AllocHGlobal (2 * valuesCount); Marshal.Copy (value, 0, this.valuePtr, valuesCount); } public EncoderParameter (Encoder encoder, long value) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeLong; this.valuePtr = Marshal.AllocHGlobal (4); Marshal.WriteInt32 (this.valuePtr, (int) value); } public EncoderParameter (Encoder encoder, long[] value) { this.encoder = encoder; this.valuesCount = value.Length; this.type = EncoderParameterValueType.ValueTypeLong; this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount); int [] ivals = new int[value.Length]; for (int i = 0; i < value.Length; i++) ivals[i] = (int) value[i]; Marshal.Copy (ivals, 0, this.valuePtr, valuesCount); } public EncoderParameter (Encoder encoder, string value) { this.encoder = encoder; ASCIIEncoding ascii = new ASCIIEncoding (); int asciiByteCount = ascii.GetByteCount (value); byte[] bytes = new byte [asciiByteCount]; ascii.GetBytes (value, 0, value.Length, bytes, 0); this.valuesCount = bytes.Length; this.type = EncoderParameterValueType.ValueTypeAscii; this.valuePtr = Marshal.AllocHGlobal (valuesCount); Marshal.Copy (bytes, 0, this.valuePtr, valuesCount); } public EncoderParameter (Encoder encoder, byte value, bool undefined) { this.encoder = encoder; this.valuesCount = 1; if (undefined) this.type = EncoderParameterValueType.ValueTypeUndefined; else this.type = EncoderParameterValueType.ValueTypeByte; this.valuePtr = Marshal.AllocHGlobal (1); Marshal.WriteByte (this.valuePtr, value); } public EncoderParameter (Encoder encoder, byte[] value, bool undefined) { this.encoder = encoder; this.valuesCount = value.Length; if (undefined) this.type = EncoderParameterValueType.ValueTypeUndefined; else this.type = EncoderParameterValueType.ValueTypeByte; this.valuePtr = Marshal.AllocHGlobal (valuesCount); Marshal.Copy (value, 0, this.valuePtr, valuesCount); } public EncoderParameter (Encoder encoder, int numerator, int denominator) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeRational; this.valuePtr = Marshal.AllocHGlobal (8); int [] valuearray = { numerator, denominator }; Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length); } public EncoderParameter (Encoder encoder, int[] numerator, int[] denominator) { if (numerator.Length != denominator.Length) throw new ArgumentException ("Invalid parameter used."); this.encoder = encoder; this.valuesCount = numerator.Length; this.type = EncoderParameterValueType.ValueTypeRational; this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2); for (int i = 0; i < valuesCount; i++) { Marshal.WriteInt32 (valuePtr, i * 4, (int) numerator[i]); Marshal.WriteInt32 (valuePtr, (i + 1) * 4, (int) denominator[i]); } } public EncoderParameter (Encoder encoder, long rangebegin, long rangeend) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeLongRange; this.valuePtr = Marshal.AllocHGlobal (8); int [] valuearray = { (int) rangebegin, (int) rangeend }; Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length); } public EncoderParameter (Encoder encoder, long[] rangebegin, long[] rangeend) { if (rangebegin.Length != rangeend.Length) throw new ArgumentException ("Invalid parameter used."); this.encoder = encoder; this.valuesCount = rangebegin.Length; this.type = EncoderParameterValueType.ValueTypeLongRange; this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2); IntPtr dest = this.valuePtr; for (int i = 0; i < valuesCount; i++) { Marshal.WriteInt32 (dest, i * 4, (int) rangebegin[i]); Marshal.WriteInt32 (dest, (i + 1) * 4, (int) rangeend[i]); } } public EncoderParameter (Encoder encoder, int numberOfValues, int type, int value) { this.encoder = encoder; this.valuePtr = (IntPtr) value; this.valuesCount = numberOfValues; this.type = (EncoderParameterValueType) type; } public EncoderParameter (Encoder encoder, int numerator1, int denominator1, int numerator2, int denominator2) { this.encoder = encoder; this.valuesCount = 1; this.type = EncoderParameterValueType.ValueTypeRationalRange; this.valuePtr = Marshal.AllocHGlobal (4 * 4); int [] valuearray = { numerator1, denominator1, numerator2, denominator2 }; Marshal.Copy (valuearray, 0, this.valuePtr, 4); } public EncoderParameter (Encoder encoder, int[] numerator1, int[] denominator1, int[] numerator2, int[] denominator2) { if (numerator1.Length != denominator1.Length || numerator2.Length != denominator2.Length || numerator1.Length != numerator2.Length) throw new ArgumentException ("Invalid parameter used."); this.encoder = encoder; this.valuesCount = numerator1.Length; this.type = EncoderParameterValueType.ValueTypeRationalRange; this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 4); IntPtr dest = this.valuePtr; for (int i = 0; i < valuesCount; i++) { Marshal.WriteInt32 (dest, i * 4, numerator1[i]); Marshal.WriteInt32 (dest, (i + 1) * 4, denominator1[i]); Marshal.WriteInt32 (dest, (i + 2) * 4, numerator2[i]); Marshal.WriteInt32 (dest, (i + 3) * 4, denominator2[i]); } } public Encoder Encoder { get { return encoder; } set { encoder = value; } } public int NumberOfValues { get { return valuesCount; } } public EncoderParameterValueType Type { get { return type; } } public EncoderParameterValueType ValueType { get { return type; } } void Dispose (bool disposing) { if (valuePtr != IntPtr.Zero) { Marshal.FreeHGlobal (valuePtr); valuePtr = IntPtr.Zero; } } public void Dispose () { Dispose (true); GC.SuppressFinalize(this); } ~EncoderParameter () { Dispose (false); } internal static int NativeSize () { return Marshal.SizeOf (typeof(GdipEncoderParameter)); } internal void ToNativePtr (IntPtr epPtr) { GdipEncoderParameter ep = new GdipEncoderParameter (); ep.guid = this.encoder.Guid; ep.numberOfValues = (uint) this.valuesCount; ep.type = this.type; ep.value = this.valuePtr; Marshal.StructureToPtr (ep, epPtr, false); } internal static EncoderParameter FromNativePtr (IntPtr epPtr) { GdipEncoderParameter ep; ep = (GdipEncoderParameter) Marshal.PtrToStructure (epPtr, typeof(GdipEncoderParameter)); Type valType; uint valCount; switch (ep.type) { case EncoderParameterValueType.ValueTypeAscii: case EncoderParameterValueType.ValueTypeByte: case EncoderParameterValueType.ValueTypeUndefined: valType = typeof(byte); valCount = ep.numberOfValues; break; case EncoderParameterValueType.ValueTypeShort: valType = typeof(short); valCount = ep.numberOfValues; break; case EncoderParameterValueType.ValueTypeLong: valType = typeof(int); valCount = ep.numberOfValues; break; case EncoderParameterValueType.ValueTypeLongRange: case EncoderParameterValueType.ValueTypeRational: valType = typeof(int); valCount = ep.numberOfValues * 2; break; case EncoderParameterValueType.ValueTypeRationalRange: valType = typeof(int); valCount = ep.numberOfValues * 4; break; default: return null; } EncoderParameter eparam = new EncoderParameter(); eparam.encoder = new Encoder(ep.guid); eparam.valuesCount = (int) ep.numberOfValues; eparam.type = ep.type; eparam.valuePtr = Marshal.AllocHGlobal ((int)(valCount * Marshal.SizeOf(valType))); /* There's nothing in Marshal to do a memcpy() between two IntPtrs. This sucks. */ unsafe { byte *s = (byte *) ep.value; byte *d = (byte *) eparam.valuePtr; for (int i = 0; i < valCount * Marshal.SizeOf(valType); i++) *d++ = *s++; } return eparam; } } }