2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[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         public sealed class EncoderParameter : IDisposable {
42
43                 private Encoder encoder;
44                 private int valuesCount;
45                 private EncoderParameterValueType type;
46                 private IntPtr valuePtr;
47
48                 internal EncoderParameter ()
49                 {
50                 }
51
52                 public EncoderParameter (Encoder encoder, byte value)
53                 {
54                         this.encoder = encoder;
55                         this.valuesCount = 1;
56                         this.type = EncoderParameterValueType.ValueTypeByte;
57                         this.valuePtr = Marshal.AllocHGlobal (1);
58                         Marshal.WriteByte (this.valuePtr, value);
59                 }
60
61                 public EncoderParameter (Encoder encoder, byte[] value)
62                 {
63                         this.encoder = encoder;
64                         this.valuesCount = value.Length;
65                         this.type = EncoderParameterValueType.ValueTypeByte;
66                         this.valuePtr = Marshal.AllocHGlobal (1 * valuesCount);
67                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
68                 }
69
70                 public EncoderParameter (Encoder encoder, short value)
71                 {
72                         this.encoder = encoder;
73                         this.valuesCount = 1;
74                         this.type = EncoderParameterValueType.ValueTypeShort;
75                         this.valuePtr = Marshal.AllocHGlobal (2);
76                         Marshal.WriteInt16 (this.valuePtr, value);
77                 }
78
79                 public EncoderParameter (Encoder encoder, short[] value)
80                 {
81                         this.encoder = encoder;
82                         this.valuesCount = value.Length;
83                         this.type = EncoderParameterValueType.ValueTypeShort;
84                         this.valuePtr = Marshal.AllocHGlobal (2 * valuesCount);
85                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
86                 }
87
88
89                 public EncoderParameter (Encoder encoder, long value)
90                 {
91                         this.encoder = encoder;
92                         this.valuesCount = 1;
93                         this.type = EncoderParameterValueType.ValueTypeLong;
94                         this.valuePtr = Marshal.AllocHGlobal (4);
95                         Marshal.WriteInt32 (this.valuePtr, (int) value);
96                 }
97
98                 public EncoderParameter (Encoder encoder, long[] value)
99                 {
100                         this.encoder = encoder;
101                         this.valuesCount = value.Length;
102                         this.type = EncoderParameterValueType.ValueTypeLong;
103                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount);
104                         int [] ivals = new int[value.Length];
105                         for (int i = 0; i < value.Length; i++) ivals[i] = (int) value[i];
106                         Marshal.Copy (ivals, 0, this.valuePtr, valuesCount);
107                 }
108
109                 public EncoderParameter (Encoder encoder, string value)
110                 {
111                         this.encoder = encoder;
112
113                         ASCIIEncoding ascii = new ASCIIEncoding ();
114                         int asciiByteCount = ascii.GetByteCount (value);
115                         byte[] bytes = new byte [asciiByteCount];
116                         ascii.GetBytes (value, 0, value.Length, bytes, 0);
117
118                         this.valuesCount = bytes.Length;
119                         this.type = EncoderParameterValueType.ValueTypeAscii;
120                         this.valuePtr = Marshal.AllocHGlobal (valuesCount);
121                         Marshal.Copy (bytes, 0, this.valuePtr, valuesCount);
122                 }
123
124                 public EncoderParameter (Encoder encoder, byte value, bool undefined)
125                 {
126                         this.encoder = encoder;
127                         this.valuesCount = 1;
128                         if (undefined)
129                                 this.type = EncoderParameterValueType.ValueTypeUndefined;
130                         else
131                                 this.type = EncoderParameterValueType.ValueTypeByte;
132                         this.valuePtr = Marshal.AllocHGlobal (1);
133                         Marshal.WriteByte (this.valuePtr, value);
134                 }
135
136                 public EncoderParameter (Encoder encoder, byte[] value, bool undefined)
137                 {
138                         this.encoder = encoder;
139                         this.valuesCount = value.Length;
140                         if (undefined)
141                                 this.type = EncoderParameterValueType.ValueTypeUndefined;
142                         else
143                                 this.type = EncoderParameterValueType.ValueTypeByte;
144                         this.valuePtr = Marshal.AllocHGlobal (valuesCount);
145                         Marshal.Copy (value, 0, this.valuePtr, valuesCount);
146                 }
147
148                 public EncoderParameter (Encoder encoder, int numerator, int denominator)
149                 {
150                         this.encoder = encoder;
151                         this.valuesCount = 1;
152                         this.type = EncoderParameterValueType.ValueTypeRational;
153                         this.valuePtr = Marshal.AllocHGlobal (8);
154                         int [] valuearray = { numerator, denominator };
155                         Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length);
156                 }
157
158                 public EncoderParameter (Encoder encoder, int[] numerator, int[] denominator)
159                 {
160                         if (numerator.Length != denominator.Length)
161                                 throw new ArgumentException ("Invalid parameter used.");
162
163                         this.encoder = encoder;
164                         this.valuesCount = numerator.Length;
165                         this.type = EncoderParameterValueType.ValueTypeRational;
166                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2);
167                         IntPtr dest = this.valuePtr;
168                         for (int i = 0; i < valuesCount; i++) {
169                                 Marshal.WriteInt32 (dest, (int) numerator[i]);
170                                 dest = (IntPtr) ((int) dest + 4);
171                                 Marshal.WriteInt32 (dest, (int) denominator[i]);
172                                 dest = (IntPtr) ((int) dest + 4);
173                         }
174                 }
175
176                 public EncoderParameter (Encoder encoder, long rangebegin, long rangeend)
177                 {
178                         this.encoder = encoder;
179                         this.valuesCount = 1;
180                         this.type = EncoderParameterValueType.ValueTypeLongRange;
181                         this.valuePtr = Marshal.AllocHGlobal (8);
182                         int [] valuearray = { (int) rangebegin, (int) rangeend };
183                         Marshal.Copy (valuearray, 0, this.valuePtr, valuearray.Length);
184                 }
185
186                 public EncoderParameter (Encoder encoder, long[] rangebegin, long[] rangeend)
187                 {
188                         if (rangebegin.Length != rangeend.Length)
189                                 throw new ArgumentException ("Invalid parameter used.");
190
191                         this.encoder = encoder;
192                         this.valuesCount = rangebegin.Length;
193                         this.type = EncoderParameterValueType.ValueTypeLongRange;
194
195                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 2);
196                         IntPtr dest = this.valuePtr;
197                         for (int i = 0; i < valuesCount; i++) {
198                                 Marshal.WriteInt32 (dest, (int) rangebegin[i]);
199                                 dest = (IntPtr) ((int) dest + 4);
200                                 Marshal.WriteInt32 (dest, (int) rangeend[i]);
201                                 dest = (IntPtr) ((int) dest + 4);
202                         }
203                 }
204
205                 public EncoderParameter (Encoder encoder, int numberOfValues, int type, int value)
206                 {
207                         this.encoder = encoder;
208                         this.valuePtr = (IntPtr) value;
209                         this.valuesCount = numberOfValues;
210                         this.type = (EncoderParameterValueType) type;
211                 }
212
213                 public EncoderParameter (Encoder encoder, int numerator1, int denominator1, int numerator2, int denominator2)
214                 {
215                         this.encoder = encoder;
216                         this.valuesCount = 1;
217                         this.type = EncoderParameterValueType.ValueTypeRationalRange;
218                         this.valuePtr = Marshal.AllocHGlobal (4 * 4);
219                         int [] valuearray = { numerator1, denominator1, numerator2, denominator2 };
220                         Marshal.Copy (valuearray, 0, this.valuePtr, 4);
221                 }
222
223                 public EncoderParameter (Encoder encoder, int[] numerator1, int[] denominator1, int[] numerator2, int[] denominator2)
224                 {
225                         if (numerator1.Length != denominator1.Length ||
226                             numerator2.Length != denominator2.Length ||
227                             numerator1.Length != numerator2.Length)
228                                 throw new ArgumentException ("Invalid parameter used.");
229
230                         this.encoder = encoder;
231                         this.valuesCount = numerator1.Length;
232                         this.type = EncoderParameterValueType.ValueTypeRationalRange;
233
234                         this.valuePtr = Marshal.AllocHGlobal (4 * valuesCount * 4);
235                         IntPtr dest = this.valuePtr;
236                         for (int i = 0; i < valuesCount; i++) {
237                                 Marshal.WriteInt32 (dest, numerator1[i]);
238                                 dest = (IntPtr) ((int) dest + 4);
239                                 Marshal.WriteInt32 (dest, denominator1[i]);
240                                 dest = (IntPtr) ((int) dest + 4);
241                                 Marshal.WriteInt32 (dest, numerator2[i]);
242                                 dest = (IntPtr) ((int) dest + 4);
243                                 Marshal.WriteInt32 (dest, denominator2[i]);
244                                 dest = (IntPtr) ((int) dest + 4);
245                         }
246                 }
247
248                 public Encoder Encoder {
249                         get {
250                                 return encoder;
251                         }
252
253                         set {
254                                 encoder = value;
255                         }
256                 }
257
258                 public int NumberOfValues {
259                         get {
260                                 return valuesCount;
261                         }
262                 }
263
264                 public EncoderParameterValueType Type {
265                         get {
266                                 return type;
267                         }
268                 }
269
270                 public EncoderParameterValueType ValueType {
271                         get {
272                                 return type;
273                         }
274                 }
275
276                 void Dispose (bool disposing) {
277                         if (valuePtr != IntPtr.Zero) {
278                                 Marshal.FreeHGlobal (valuePtr);
279                                 valuePtr = IntPtr.Zero;
280                         }
281                 }
282
283                 public void Dispose () {
284                         Dispose (true);         
285                 }
286
287                 ~EncoderParameter () {
288                         Dispose (false);
289                 }
290
291                 internal static int NativeSize () {
292                         return Marshal.SizeOf (typeof(GdipEncoderParameter));
293                 }
294
295                 internal void ToNativePtr (IntPtr epPtr) {
296                         GdipEncoderParameter ep = new GdipEncoderParameter ();
297                         ep.guid = this.encoder.Guid;
298                         ep.numberOfValues = (uint) this.valuesCount;
299                         ep.type = this.type;
300                         ep.value = this.valuePtr;
301                         Marshal.StructureToPtr (ep, epPtr, false);
302                 }
303
304                 internal static EncoderParameter FromNativePtr (IntPtr epPtr) {
305                         GdipEncoderParameter ep;
306                         ep = (GdipEncoderParameter) Marshal.PtrToStructure (epPtr, typeof(GdipEncoderParameter));
307
308                         Type valType;
309                         uint valCount;
310
311                         switch (ep.type) {
312                         case EncoderParameterValueType.ValueTypeAscii:
313                         case EncoderParameterValueType.ValueTypeByte:
314                         case EncoderParameterValueType.ValueTypeUndefined:
315                                 valType = typeof(byte);
316                                 valCount = ep.numberOfValues;
317                                 break;
318                         case EncoderParameterValueType.ValueTypeShort:
319                                 valType = typeof(short);
320                                 valCount = ep.numberOfValues;
321                                 break;
322                         case EncoderParameterValueType.ValueTypeLong:
323                                 valType = typeof(int);
324                                 valCount = ep.numberOfValues;
325                                 break;
326                         case EncoderParameterValueType.ValueTypeLongRange:
327                         case EncoderParameterValueType.ValueTypeRational:
328                                 valType = typeof(int);
329                                 valCount = ep.numberOfValues * 2;
330                                 break;
331                         case EncoderParameterValueType.ValueTypeRationalRange:
332                                 valType = typeof(int);
333                                 valCount = ep.numberOfValues * 4;
334                                 break;
335                         default:
336                                 return null;
337                         }
338
339                         EncoderParameter eparam = new EncoderParameter();
340                         eparam.encoder = new Encoder(ep.guid);
341                         eparam.valuesCount = (int) ep.numberOfValues;
342                         eparam.type = ep.type;
343                         eparam.valuePtr = Marshal.AllocHGlobal ((int)(valCount * Marshal.SizeOf(valType)));
344
345                         /* There's nothing in Marshal to do a memcpy() between two IntPtrs.  This sucks. */
346                         unsafe {
347                                 byte *s = (byte *) ep.value;
348                                 byte *d = (byte *) eparam.valuePtr;
349                                 for (int i = 0; i < valCount * Marshal.SizeOf(valType); i++)
350                                         *d++ = *s++;
351                         }
352
353                         return eparam;
354                 }
355         }
356 }