In mono_thread_info_suspend_lock in non-coop, don't assert MonoThreadInfo* is non...
[mono.git] / mcs / class / System.Drawing / System.Drawing.Imaging / EncoderParameter.cs
1 //
2 // System.Drawing.Imaging.EncoderParameter.cs
3 //
4 // Author: 
5 //      Ravindra (rkumar@novell.com)
6 //  Vladimir Vukicevic (vladimir@pobox.com)
7 //
8 // (C) 2004 Novell, Inc.  http://www.novell.com
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Text;
36
37 using System.Runtime.InteropServices;
38
39 namespace System.Drawing.Imaging {
40
41         [StructLayout(LayoutKind.Sequential)]
42         public sealed class EncoderParameter : IDisposable {
43
44                 private Encoder encoder;
45                 private int valuesCount;
46                 private EncoderParameterValueType type;
47                 private IntPtr valuePtr;
48
49                 internal EncoderParameter ()
50                 {
51                 }
52
53                 public EncoderParameter (Encoder encoder, byte value)
54                 {
55                         this.encoder = encoder;
56                         this.valuesCount = 1;
57                         this.type = EncoderParameterValueType.ValueTypeByte;
58                         this.valuePtr = Marshal.AllocHGlobal (1);
59                         Marshal.WriteByte (this.valuePtr, value);
60                 }
61
62                 public EncoderParameter (Encoder encoder, byte[] value)
63                 {
64                         this.encoder = encoder;
65                         this.valuesCount = value.Length;
66                         this.type = EncoderParameterValueType.ValueTypeByte;
67                         this.valuePtr = Marshal.AllocHGlobal (1 * valuesCount);
68                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
69                 }
70
71                 public EncoderParameter (Encoder encoder, short value)
72                 {
73                         this.encoder = encoder;
74                         this.valuesCount = 1;
75                         this.type = EncoderParameterValueType.ValueTypeShort;
76                         this.valuePtr = Marshal.AllocHGlobal (2);
77                         Marshal.WriteInt16 (this.valuePtr, value);
78                 }
79
80                 public EncoderParameter (Encoder encoder, short[] value)
81                 {
82                         this.encoder = encoder;
83                         this.valuesCount = value.Length;
84                         this.type = EncoderParameterValueType.ValueTypeShort;
85                         this.valuePtr = Marshal.AllocHGlobal (2 * valuesCount);
86                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
87                 }
88
89
90                 public EncoderParameter (Encoder encoder, long value)
91                 {
92                         this.encoder = encoder;
93                         this.valuesCount = 1;
94                         this.type = EncoderParameterValueType.ValueTypeLong;
95                         this.valuePtr = Marshal.AllocHGlobal (4);
96                         Marshal.WriteInt32 (this.valuePtr, (int) value);
97                 }
98
99                 public EncoderParameter (Encoder encoder, long[] value)
100                 {
101                         this.encoder = encoder;
102                         this.valuesCount = value.Length;
103                         this.type = EncoderParameterValueType.ValueTypeLong;
104                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount);
105                         int [] ivals = new int[value.Length];
106                         for (int i = 0; i < value.Length; i++) ivals[i] = (int) value[i];
107                         Marshal.Copy (ivals, 0, this.valuePtr, valuesCount);
108                 }
109
110                 public EncoderParameter (Encoder encoder, string value)
111                 {
112                         this.encoder = encoder;
113
114                         ASCIIEncoding ascii = new ASCIIEncoding ();
115                         int asciiByteCount = ascii.GetByteCount (value);
116                         byte[] bytes = new byte [asciiByteCount];
117                         ascii.GetBytes (value, 0, value.Length, bytes, 0);
118
119                         this.valuesCount = bytes.Length;
120                         this.type = EncoderParameterValueType.ValueTypeAscii;
121                         this.valuePtr = Marshal.AllocHGlobal (valuesCount);
122                         Marshal.Copy (bytes, 0, this.valuePtr, valuesCount);
123                 }
124
125                 public EncoderParameter (Encoder encoder, byte value, bool undefined)
126                 {
127                         this.encoder = encoder;
128                         this.valuesCount = 1;
129                         if (undefined)
130                                 this.type = EncoderParameterValueType.ValueTypeUndefined;
131                         else
132                                 this.type = EncoderParameterValueType.ValueTypeByte;
133                         this.valuePtr = Marshal.AllocHGlobal (1);
134                         Marshal.WriteByte (this.valuePtr, value);
135                 }
136
137                 public EncoderParameter (Encoder encoder, byte[] value, bool undefined)
138                 {
139                         this.encoder = encoder;
140                         this.valuesCount = value.Length;
141                         if (undefined)
142                                 this.type = EncoderParameterValueType.ValueTypeUndefined;
143                         else
144                                 this.type = EncoderParameterValueType.ValueTypeByte;
145                         this.valuePtr = Marshal.AllocHGlobal (valuesCount);
146                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
147                 }
148
149                 public EncoderParameter (Encoder encoder, int numerator, int denominator)
150                 {
151                         this.encoder = encoder;
152                         this.valuesCount = 1;
153                         this.type = EncoderParameterValueType.ValueTypeRational;
154                         this.valuePtr = Marshal.AllocHGlobal (8);
155                         int [] valuearray = { numerator, denominator };
156                         Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length);
157                 }
158
159                 public EncoderParameter (Encoder encoder, int[] numerator, int[] denominator)
160                 {
161                         if (numerator.Length != denominator.Length)
162                                 throw new ArgumentException ("Invalid parameter used.");
163
164                         this.encoder = encoder;
165                         this.valuesCount = numerator.Length;
166                         this.type = EncoderParameterValueType.ValueTypeRational;
167                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2);
168                         for (int i = 0; i < valuesCount; i++) {
169                                 Marshal.WriteInt32 (valuePtr, i * 4, (int) numerator[i]);
170                                 Marshal.WriteInt32 (valuePtr, (i + 1) * 4, (int) denominator[i]);
171                         }
172                 }
173
174                 public EncoderParameter (Encoder encoder, long rangebegin, long rangeend)
175                 {
176                         this.encoder = encoder;
177                         this.valuesCount = 1;
178                         this.type = EncoderParameterValueType.ValueTypeLongRange;
179                         this.valuePtr = Marshal.AllocHGlobal (8);
180                         int [] valuearray = { (int) rangebegin, (int) rangeend };
181                         Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length);
182                 }
183
184                 public EncoderParameter (Encoder encoder, long[] rangebegin, long[] rangeend)
185                 {
186                         if (rangebegin.Length != rangeend.Length)
187                                 throw new ArgumentException ("Invalid parameter used.");
188
189                         this.encoder = encoder;
190                         this.valuesCount = rangebegin.Length;
191                         this.type = EncoderParameterValueType.ValueTypeLongRange;
192
193                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2);
194                         IntPtr dest = this.valuePtr;
195                         for (int i = 0; i < valuesCount; i++) {
196                                 Marshal.WriteInt32 (dest, i * 4, (int) rangebegin[i]);
197                                 Marshal.WriteInt32 (dest, (i + 1) * 4, (int) rangeend[i]);
198                         }
199                 }
200
201                 public EncoderParameter (Encoder encoder, int NumberOfValues, int Type, int Value)
202                 {
203                         this.encoder = encoder;
204                         this.valuePtr = (IntPtr) Value;
205                         this.valuesCount = NumberOfValues;
206                         this.type = (EncoderParameterValueType) Type;
207                 }
208
209                 public EncoderParameter (Encoder encoder, int numerator1, int demoninator1, int numerator2, int demoninator2)
210                 {
211                         this.encoder = encoder;
212                         this.valuesCount = 1;
213                         this.type = EncoderParameterValueType.ValueTypeRationalRange;
214                         this.valuePtr = Marshal.AllocHGlobal (4 * 4);
215                         int [] valuearray = { numerator1, demoninator1, numerator2, demoninator2 };
216                         Marshal.Copy (valuearray, 0, this.valuePtr, 4);
217                 }
218
219                 public EncoderParameter (Encoder encoder, int[] numerator1, int[] denominator1, int[] numerator2, int[] denominator2)
220                 {
221                         if (numerator1.Length != denominator1.Length ||
222                             numerator2.Length != denominator2.Length ||
223                             numerator1.Length != numerator2.Length)
224                                 throw new ArgumentException ("Invalid parameter used.");
225
226                         this.encoder = encoder;
227                         this.valuesCount = numerator1.Length;
228                         this.type = EncoderParameterValueType.ValueTypeRationalRange;
229
230                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 4);
231                         IntPtr dest = this.valuePtr;
232                         for (int i = 0; i < valuesCount; i++) {
233                                 Marshal.WriteInt32 (dest, i * 4, numerator1[i]);
234                                 Marshal.WriteInt32 (dest, (i + 1) * 4, denominator1[i]);
235                                 Marshal.WriteInt32 (dest, (i + 2) * 4, numerator2[i]);
236                                 Marshal.WriteInt32 (dest, (i + 3) * 4, denominator2[i]);
237                         }
238                 }
239
240                 public Encoder Encoder {
241                         get {
242                                 return encoder;
243                         }
244
245                         set {
246                                 encoder = value;
247                         }
248                 }
249
250                 public int NumberOfValues {
251                         get {
252                                 return valuesCount;
253                         }
254                 }
255
256                 public EncoderParameterValueType Type {
257                         get {
258                                 return type;
259                         }
260                 }
261
262                 public EncoderParameterValueType ValueType {
263                         get {
264                                 return type;
265                         }
266                 }
267
268                 void Dispose (bool disposing) {
269                         if (valuePtr != IntPtr.Zero) {
270                                 Marshal.FreeHGlobal (valuePtr);
271                                 valuePtr = IntPtr.Zero;
272                         }
273                 }
274
275                 public void Dispose () {
276                         Dispose (true);         
277                         GC.SuppressFinalize(this);
278                 }
279
280                 ~EncoderParameter () {
281                         Dispose (false);
282                 }
283
284                 internal static int NativeSize () {
285                         return Marshal.SizeOf (typeof(GdipEncoderParameter));
286                 }
287
288                 internal void ToNativePtr (IntPtr epPtr) {
289                         GdipEncoderParameter ep = new GdipEncoderParameter ();
290                         ep.guid = this.encoder.Guid;
291                         ep.numberOfValues = (uint) this.valuesCount;
292                         ep.type = this.type;
293                         ep.value = this.valuePtr;
294                         Marshal.StructureToPtr (ep, epPtr, false);
295                 }
296
297                 internal static EncoderParameter FromNativePtr (IntPtr epPtr) {
298                         GdipEncoderParameter ep;
299                         ep = (GdipEncoderParameter) Marshal.PtrToStructure (epPtr, typeof(GdipEncoderParameter));
300
301                         Type valType;
302                         uint valCount;
303
304                         switch (ep.type) {
305                         case EncoderParameterValueType.ValueTypeAscii:
306                         case EncoderParameterValueType.ValueTypeByte:
307                         case EncoderParameterValueType.ValueTypeUndefined:
308                                 valType = typeof(byte);
309                                 valCount = ep.numberOfValues;
310                                 break;
311                         case EncoderParameterValueType.ValueTypeShort:
312                                 valType = typeof(short);
313                                 valCount = ep.numberOfValues;
314                                 break;
315                         case EncoderParameterValueType.ValueTypeLong:
316                                 valType = typeof(int);
317                                 valCount = ep.numberOfValues;
318                                 break;
319                         case EncoderParameterValueType.ValueTypeLongRange:
320                         case EncoderParameterValueType.ValueTypeRational:
321                                 valType = typeof(int);
322                                 valCount = ep.numberOfValues * 2;
323                                 break;
324                         case EncoderParameterValueType.ValueTypeRationalRange:
325                                 valType = typeof(int);
326                                 valCount = ep.numberOfValues * 4;
327                                 break;
328                         default:
329                                 return null;
330                         }
331
332                         EncoderParameter eparam = new EncoderParameter();
333                         eparam.encoder = new Encoder(ep.guid);
334                         eparam.valuesCount = (int) ep.numberOfValues;
335                         eparam.type = ep.type;
336                         eparam.valuePtr = Marshal.AllocHGlobal ((int)(valCount * Marshal.SizeOf(valType)));
337
338                         /* There's nothing in Marshal to do a memcpy() between two IntPtrs.  This sucks. */
339                         unsafe {
340                                 byte *s = (byte *) ep.value;
341                                 byte *d = (byte *) eparam.valuePtr;
342                                 for (int i = 0; i < valCount * Marshal.SizeOf(valType); i++)
343                                         *d++ = *s++;
344                         }
345
346                         return eparam;
347                 }
348         }
349 }