corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 #region Using Statements
2 using System;
3 using System.Collections.Generic;
4 using System.Drawing;
5 using System.Drawing.Imaging;
6 using System.IO;
7 using System.Text;
8 using CSJ2K;
9 using CSJ2K.Color;
10 using CSJ2K.Icc;
11 using CSJ2K.j2k;
12 using CSJ2K.j2k.codestream;
13 using CSJ2K.j2k.codestream.reader;
14 using CSJ2K.j2k.decoder;
15 using CSJ2K.j2k.entropy.decoder;
16 using CSJ2K.j2k.fileformat.reader;
17 using CSJ2K.j2k.image;
18 using CSJ2K.j2k.image.invcomptransf;
19 using CSJ2K.j2k.io;
20 using CSJ2K.j2k.quantization.dequantizer;
21 using CSJ2K.j2k.roi;
22 using CSJ2K.j2k.util;
23 using CSJ2K.j2k.wavelet.synthesis;
24 #endregion
25  
26 namespace CSJ2K
27 {
28 public class J2kImage
29 {
30 #region Static Decoder Methods
31 public static Image FromFile(string filename)
32 {
33 Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
34 Image img = FromStream(stream);
35 stream.Close();
36 return (img);
37 }
38  
39 public static Image FromBytes(byte[] j2kdata)
40 {
41 return FromStream(new MemoryStream(j2kdata));
42 }
43  
44 public static Image FromStream(Stream stream)
45 {
46 RandomAccessIO in_stream = new ISRandomAccessIO(stream);
47  
48 // Initialize default parameters
49 ParameterList defpl = GetDefaultParameterList(decoder_pinfo);
50  
51 // Create parameter list using defaults
52 ParameterList pl = new ParameterList(defpl);
53  
54 // **** File Format ****
55 // If the codestream is wrapped in the jp2 fileformat, Read the
56 // file format wrapper
57 FileFormatReader ff = new FileFormatReader(in_stream);
58 ff.readFileFormat();
59 if (ff.JP2FFUsed)
60 {
61 in_stream.seek(ff.FirstCodeStreamPos);
62 }
63  
64 // +----------------------------+
65 // | Instantiate decoding chain |
66 // +----------------------------+
67  
68 // **** Header decoder ****
69 // Instantiate header decoder and read main header
70 HeaderInfo hi = new HeaderInfo();
71 HeaderDecoder hd;
72 try
73 {
74 hd = new HeaderDecoder(in_stream, pl, hi);
75 }
76 catch (EndOfStreamException e)
77 {
78 throw new ApplicationException("Codestream too short or bad header, unable to decode.", e);
79 }
80  
81 int nCompCod = hd.NumComps;
82 int nTiles = hi.sizValue.NumTiles;
83 DecoderSpecs decSpec = hd.DecoderSpecs;
84  
85 // Get demixed bitdepths
86 int[] depth = new int[nCompCod];
87 for (int i = 0; i < nCompCod; i++)
88 {
89 depth[i] = hd.getOriginalBitDepth(i);
90 }
91  
92 // **** Bit stream reader ****
93 BitstreamReaderAgent breader;
94 try
95 {
96 breader = BitstreamReaderAgent.
97 createInstance(in_stream, hd, pl, decSpec,
98 false, hi);
99 }
100 catch (IOException e)
101 {
102 throw new ApplicationException("Error while reading bit stream header or parsing packets.", e);
103 }
104 catch (ArgumentException e)
105 {
106 throw new ApplicationException("Cannot instantiate bit stream reader.", e);
107 }
108  
109 // **** Entropy decoder ****
110 EntropyDecoder entdec;
111 try
112 {
113 entdec = hd.createEntropyDecoder(breader, pl);
114 }
115 catch (ArgumentException e)
116 {
117 throw new ApplicationException("Cannot instantiate entropy decoder.", e);
118 }
119  
120 // **** ROI de-scaler ****
121 ROIDeScaler roids;
122 try
123 {
124 roids = hd.createROIDeScaler(entdec, pl, decSpec);
125 }
126 catch (ArgumentException e)
127 {
128 throw new ApplicationException("Cannot instantiate roi de-scaler.", e);
129 }
130  
131 // **** Dequantizer ****
132 Dequantizer deq;
133 try
134 {
135 deq = hd.createDequantizer(roids, depth, decSpec);
136 }
137 catch (ArgumentException e)
138 {
139 throw new ApplicationException("Cannot instantiate dequantizer.", e);
140 }
141  
142 // **** Inverse wavelet transform ***
143 InverseWT invWT;
144 try
145 {
146 // full page inverse wavelet transform
147 invWT = InverseWT.createInstance(deq, decSpec);
148 }
149 catch (ArgumentException e)
150 {
151 throw new ApplicationException("Cannot instantiate inverse wavelet transform.", e);
152 }
153  
154 int res = breader.ImgRes;
155 invWT.ImgResLevel = res;
156  
157 // **** Data converter **** (after inverse transform module)
158 ImgDataConverter converter = new ImgDataConverter(invWT, 0);
159  
160 // **** Inverse component transformation ****
161 InvCompTransf ictransf = new InvCompTransf(converter, decSpec, depth, pl);
162  
163 // **** Color space mapping ****
164 BlkImgDataSrc color;
165 if (ff.JP2FFUsed && pl.getParameter("nocolorspace").Equals("off"))
166 {
167 try
168 {
169 ColorSpace csMap = new ColorSpace(in_stream, hd, pl);
170 BlkImgDataSrc channels = hd.createChannelDefinitionMapper(ictransf, csMap);
171 BlkImgDataSrc resampled = hd.createResampler(channels, csMap);
172 BlkImgDataSrc palettized = hd.createPalettizedColorSpaceMapper(resampled, csMap);
173 color = hd.createColorSpaceMapper(palettized, csMap);
174 }
175 catch (ArgumentException e)
176 {
177 throw new ApplicationException("Could not instantiate ICC profiler.", e);
178 }
179 catch (ColorSpaceException e)
180 {
181 throw new ApplicationException("Error processing ColorSpace information.", e);
182 }
183 }
184 else
185 { // Skip colorspace mapping
186 color = ictransf;
187 }
188  
189 // This is the last image in the decoding chain and should be
190 // assigned by the last transformation:
191 BlkImgDataSrc decodedImage = color;
192 if (color == null)
193 {
194 decodedImage = ictransf;
195 }
196 int numComps = decodedImage.NumComps;
197 int bytesPerPixel = numComps; // Assuming 8-bit components
198  
199 // **** Copy to Bitmap ****
200 PixelFormat pixelFormat;
201 switch (numComps)
202 {
203 case 1:
204 pixelFormat = PixelFormat.Format24bppRgb; break;
205 case 3:
206 pixelFormat = PixelFormat.Format24bppRgb; break;
207 case 4:
208 case 5:
209 pixelFormat = PixelFormat.Format32bppArgb; break;
210 default:
211 throw new ApplicationException("Unsupported PixelFormat. " + numComps + " components.");
212 }
213  
214 Bitmap dst = new Bitmap(decodedImage.ImgWidth, decodedImage.ImgHeight, pixelFormat);
215  
216 Coord numTiles = decodedImage.getNumTiles(null);
217  
218 int tIdx = 0;
219  
220 for (int y = 0; y < numTiles.y; y++)
221 {
222 // Loop on horizontal tiles
223 for (int x = 0; x < numTiles.x; x++, tIdx++)
224 {
225 decodedImage.setTile(x, y);
226  
227 int height = decodedImage.getTileCompHeight(tIdx, 0);
228 int width = decodedImage.getTileCompWidth(tIdx, 0);
229  
230 int tOffx = decodedImage.getCompULX(0) -
231 (int)Math.Ceiling(decodedImage.ImgULX /
232 (double)decodedImage.getCompSubsX(0));
233  
234 int tOffy = decodedImage.getCompULY(0) -
235 (int)Math.Ceiling(decodedImage.ImgULY /
236 (double)decodedImage.getCompSubsY(0));
237  
238 DataBlkInt[] db = new DataBlkInt[numComps];
239 int[] ls = new int[numComps];
240 int[] mv = new int[numComps];
241 int[] fb = new int[numComps];
242 for (int i = 0; i < numComps; i++)
243 {
244 db[i] = new DataBlkInt();
245 ls[i] = 1 << (decodedImage.getNomRangeBits(0) - 1);
246 mv[i] = (1 << decodedImage.getNomRangeBits(0)) - 1;
247 fb[i] = decodedImage.getFixedPoint(0);
248 }
249 for (int l = 0; l < height; l++)
250 {
251 for (int i = numComps - 1; i >= 0; i--)
252 {
253 db[i].ulx = 0;
254 db[i].uly = l;
255 db[i].w = width;
256 db[i].h = 1;
257 decodedImage.getInternCompData(db[i], i);
258 }
259 int[] k = new int[numComps];
260 for (int i = numComps - 1; i >= 0; i--) k[i] = db[i].offset + width - 1;
261  
262 int outputBytesPerPixel = Math.Max(3, Math.Min(4, bytesPerPixel));
263 byte[] rowvalues = new byte[width * outputBytesPerPixel];
264  
265 for (int i = width - 1; i >= 0; i--)
266 {
267 int[] tmp = new int[numComps];
268 for (int j = numComps - 1; j >= 0; j--)
269 {
270 tmp[j] = (db[j].data_array[k[j]--] >> fb[j]) + ls[j];
271 tmp[j] = (tmp[j] < 0) ? 0 : ((tmp[j] > mv[j]) ? mv[j] : tmp[j]);
272  
273 if (decodedImage.getNomRangeBits(j) != 8)
274 tmp[j] = (int)Math.Round(((double)tmp[j] / Math.Pow(2D, (double)decodedImage.getNomRangeBits(j))) * 255D);
275  
276 }
277 int offset = i * outputBytesPerPixel;
278 switch (numComps)
279 {
280 case 1:
281 rowvalues[offset + 0] = (byte)tmp[0];
282 rowvalues[offset + 1] = (byte)tmp[0];
283 rowvalues[offset + 2] = (byte)tmp[0];
284 break;
285 case 3:
286 rowvalues[offset + 0] = (byte)tmp[2];
287 rowvalues[offset + 1] = (byte)tmp[1];
288 rowvalues[offset + 2] = (byte)tmp[0];
289 break;
290 case 4:
291 case 5:
292 rowvalues[offset + 0] = (byte)tmp[2];
293 rowvalues[offset + 1] = (byte)tmp[1];
294 rowvalues[offset + 2] = (byte)tmp[0];
295 rowvalues[offset + 3] = (byte)tmp[3];
296 break;
297 }
298 }
299  
300 BitmapData dstdata = dst.LockBits(
301 new System.Drawing.Rectangle(tOffx, tOffy + l, width, 1),
302 ImageLockMode.WriteOnly, pixelFormat);
303  
304 IntPtr ptr = dstdata.Scan0;
305 System.Runtime.InteropServices.Marshal.Copy(rowvalues, 0, ptr, rowvalues.Length);
306 dst.UnlockBits(dstdata);
307 }
308 }
309 }
310 return dst;
311 }
312  
313 public static List<int> GetLayerBoundaries(Stream stream)
314 {
315 RandomAccessIO in_stream = new ISRandomAccessIO(stream);
316  
317 // Create parameter list using defaults
318 ParameterList pl = new ParameterList(GetDefaultParameterList(decoder_pinfo));
319  
320 // **** File Format ****
321 // If the codestream is wrapped in the jp2 fileformat, Read the
322 // file format wrapper
323 FileFormatReader ff = new FileFormatReader(in_stream);
324 ff.readFileFormat();
325 if (ff.JP2FFUsed)
326 {
327 in_stream.seek(ff.FirstCodeStreamPos);
328 }
329  
330 // +----------------------------+
331 // | Instantiate decoding chain |
332 // +----------------------------+
333  
334 // **** Header decoder ****
335 // Instantiate header decoder and read main header
336 HeaderInfo hi = new HeaderInfo();
337 HeaderDecoder hd;
338 try
339 {
340 hd = new HeaderDecoder(in_stream, pl, hi);
341 }
342 catch (EndOfStreamException e)
343 {
344 throw new ArgumentException("Codestream too short or bad header, unable to decode.", e);
345 }
346  
347 int nCompCod = hd.NumComps;
348 int nTiles = hi.sizValue.NumTiles;
349 DecoderSpecs decSpec = hd.DecoderSpecs;
350  
351 // Get demixed bitdepths
352 int[] depth = new int[nCompCod];
353 for (int i = 0; i < nCompCod; i++)
354 {
355 depth[i] = hd.getOriginalBitDepth(i);
356 }
357  
358 // **** Bit stream reader ****
359 BitstreamReaderAgent breader;
360 try
361 {
362 breader = BitstreamReaderAgent.createInstance(in_stream, hd, pl, decSpec, false, hi);
363 }
364 catch (IOException e)
365 {
366 throw new ArgumentException("Error while reading bit stream header or parsing packets.", e);
367 }
368 catch (ArgumentException e)
369 {
370 throw new ArgumentException("Cannot instantiate bit stream reader.", e);
371 }
372  
373 breader.setTile(0, 0);
374  
375 return ((FileBitstreamReaderAgent)breader).layerStarts;
376 }
377  
378 #endregion
379  
380 #region Static Encoder Methods
381  
382 public static void ToFile(Bitmap bitmap, string filename)
383 {
384 using (FileStream stream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite))
385 {
386 ToStream(bitmap, stream);
387 }
388 }
389 public static byte[] ToArray(Bitmap bitmap)
390 {
391 using (MemoryStream stream = new MemoryStream())
392 {
393 ToStream(bitmap, stream);
394 return stream.ToArray();
395 }
396 }
397 public static void ToStream(Bitmap bitmap, Stream stream)
398 {
399 throw new NotImplementedException();
400 }
401  
402 #endregion
403  
404 #region Default Parameter Loader
405 public static ParameterList GetDefaultParameterList(string[][] pinfo)
406 {
407 ParameterList pl = new ParameterList();
408 string[][] str;
409  
410 str = BitstreamReaderAgent.ParameterInfo;
411 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
412 pl.Set(str[i][0], str[i][3]);
413  
414 str = EntropyDecoder.ParameterInfo;
415 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
416 pl.Set(str[i][0], str[i][3]);
417  
418 str = ROIDeScaler.ParameterInfo;
419 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
420 pl.Set(str[i][0], str[i][3]);
421  
422 str = Dequantizer.ParameterInfo;
423 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
424 pl.Set(str[i][0], str[i][3]);
425  
426 str = InvCompTransf.ParameterInfo;
427 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
428 pl.Set(str[i][0], str[i][3]);
429  
430 str = HeaderDecoder.ParameterInfo;
431 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
432 pl.Set(str[i][0], str[i][3]);
433  
434 str = ICCProfiler.ParameterInfo;
435 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
436 pl.Set(str[i][0], str[i][3]);
437  
438 str = pinfo;
439 if (str != null) for (int i = str.Length - 1; i >= 0; i--)
440 pl.Set(str[i][0], str[i][3]);
441  
442 return pl;
443 }
444 #endregion
445  
446 #region Decoder Parameters
447 private static String[][] decoder_pinfo = {
448 new string[] { "u", "[on|off]",
449 "Prints usage information. "+
450 "If specified all other arguments (except 'v') are ignored","off"},
451 new string[] { "v", "[on|off]",
452 "Prints version and copyright information","off"},
453 new string[] { "verbose", "[on|off]",
454 "Prints information about the decoded codestream","on"},
455 new string[] { "pfile", "<filename>",
456 "Loads the arguments from the specified file. Arguments that are "+
457 "specified on the command line override the ones from the file.\n"+
458 "The arguments file is a simple text file with one argument per "+
459 "line of the following form:\n" +
460 " <argument name>=<argument value>\n"+
461 "If the argument is of boolean type (i.e. its presence turns a "+
462 "feature on), then the 'on' value turns it on, while the 'off' "+
463 "value turns it off. The argument name does not include the '-' "+
464 "or '+' character. Long lines can be broken into several lines "+
465 "by terminating them with '\\'. Lines starting with '#' are "+
466 "considered as comments. This option is not recursive: any 'pfile' "+
467 "argument appearing in the file is ignored.",null},
468 new string[] { "res", "<resolution level index>",
469 "The resolution level at which to reconstruct the image "+
470 " (0 means the lowest available resolution whereas the maximum "+
471 "resolution level corresponds to the original image resolution). "+
472 "If the given index"+
473 " is greater than the number of available resolution levels of the "+
474 "compressed image, the image is reconstructed at its highest "+
475 "resolution (among all tile-components). Note that this option"+
476 " affects only the inverse wavelet transform and not the number "+
477 " of bytes read by the codestream parser: this number of bytes "+
478 "depends only on options '-nbytes' or '-rate'.", null},
479 new string[] { "i", "<filename or url>",
480 "The file containing the JPEG 2000 compressed data. This can be "+
481 "either a JPEG 2000 codestream or a JP2 file containing a "+
482 "JPEG 2000 "+
483 "codestream. In the latter case the first codestream in the file "+
484 "will be decoded. If an URL is specified (e.g., http://...) "+
485 "the data will be downloaded and cached in memory before decoding. "+
486 "This is intended for easy use in applets, but it is not a very "+
487 "efficient way of decoding network served data.", null},
488 new string[] { "o", "<filename>",
489 "This is the name of the file to which the decompressed image "+
490 "is written. If no output filename is given, the image is "+
491 "displayed on the screen. "+
492 "Output file format is PGX by default. If the extension"+
493 " is '.pgm' then a PGM file is written as output, however this is "+
494 "only permitted if the component bitdepth does not exceed 8. If "+
495 "the extension is '.ppm' then a PPM file is written, however this "+
496 "is only permitted if there are 3 components and none of them has "+
497 "a bitdepth of more than 8. If there is more than 1 component, "+
498 "suffices '-1', '-2', '-3', ... are added to the file name, just "+
499 "before the extension, except for PPM files where all three "+
500 "components are written to the same file.",null},
501 new string[] { "rate","<decoding rate in bpp>",
502 "Specifies the decoding rate in bits per pixel (bpp) where the "+
503 "number of pixels is related to the image's original size (Note:"+
504 " this number is not affected by the '-res' option). If it is equal"+
505 "to -1, the whole codestream is decoded. "+
506 "The codestream is either parsed (default) or truncated depending "+
507 "the command line option '-parsing'. To specify the decoding "+
508 "rate in bytes, use '-nbytes' options instead.","-1"},
509 new string[] { "nbytes","<decoding rate in bytes>",
510 "Specifies the decoding rate in bytes. "+
511 "The codestream is either parsed (default) or truncated depending "+
512 "the command line option '-parsing'. To specify the decoding "+
513 "rate in bits per pixel, use '-rate' options instead.","-1"},
514 new string[] { "parsing", null,
515 "Enable or not the parsing mode when decoding rate is specified "+
516 "('-nbytes' or '-rate' options). If it is false, the codestream "+
517 "is decoded as if it were truncated to the given rate. If it is "+
518 "true, the decoder creates, truncates and decodes a virtual layer"+
519 " progressive codestream with the same truncation points in each "+
520 "code-block.","on"},
521 new string[] { "ncb_quit","<max number of code blocks>",
522 "Use the ncb and lbody quit conditions. If state information is "+
523 "found for more code blocks than is indicated with this option, "+
524 "the decoder "+
525 "will decode using only information found before that point. "+
526 "Using this otion implies that the 'rate' or 'nbyte' parameter "+
527 "is used to indicate the lbody parameter which is the number of "+
528 "packet body bytes the decoder will decode.","-1"},
529 new string[] { "l_quit","<max number of layers>",
530 "Specifies the maximum number of layers to decode for any code-"+
531 "block","-1"},
532 new string[] { "m_quit","<max number of bit planes>",
533 "Specifies the maximum number of bit planes to decode for any code"+
534 "-block","-1"},
535 new string[] { "poc_quit",null,
536 "Specifies the whether the decoder should only decode code-blocks "+
537 "included in the first progression order.","off"},
538 new string[] { "one_tp",null,
539 "Specifies whether the decoder should only decode the first "+
540 "tile part of each tile.","off"},
541 new string[] { "comp_transf",null,
542 "Specifies whether the component transform indicated in the "+
543 "codestream should be used.","on"},
544 new string[] { "debug", null,
545 "Print debugging messages when an error is encountered.","off"},
546 new string[] { "cdstr_info", null,
547 "Display information about the codestream. This information is: "+
548 "\n- Marker segments value in main and tile-part headers,"+
549 "\n- Tile-part length and position within the code-stream.", "off"},
550 new string[] { "nocolorspace",null,
551 "Ignore any colorspace information in the image.","off"},
552 new string[] { "colorspace_debug", null,
553 "Print debugging messages when an error is encountered in the"+
554 " colorspace module.","off"}
555 };
556 #endregion
557  
558 #region Encoder Parameters
559 private static String[][] encoder_pinfo = {
560 new string[] { "debug", null,
561 "Print debugging messages when an error is encountered.","off"},
562 new string[] { "disable_jp2_extension", "[on|off]",
563 "JJ2000 automatically adds .jp2 extension when using 'file_format'"+
564 "option. This option disables it when on.", "off"},
565 new string[] { "file_format", "[on|off]",
566 "Puts the JPEG 2000 codestream in a JP2 file format wrapper.","off"},
567 new string[] { "pph_tile", "[on|off]",
568 "Packs the packet headers in the tile headers.","off"},
569 new string[] { "pph_main", "[on|off]",
570 "Packs the packet headers in the main header.","off"},
571 new string[] { "pfile", "<filename of arguments file>",
572 "Loads the arguments from the specified file. Arguments that are "+
573 "specified on the command line override the ones from the file.\n"+
574 "The arguments file is a simple text file with one argument per "+
575 "line of the following form:\n" +
576 " <argument name>=<argument value>\n"+
577 "If the argument is of boolean type (i.e. its presence turns a "+
578 "feature on), then the 'on' value turns it on, while the 'off' "+
579 "value turns it off. The argument name does not include the '-' "+
580 "or '+' character. Long lines can be broken into several lines "+
581 "by terminating them with '\'. Lines starting with '#' are "+
582 "considered as comments. This option is not recursive: any 'pfile' "+
583 "argument appearing in the file is ignored.",null},
584 new string[] { "tile_parts", "<packets per tile-part>",
585 "This option specifies the maximum number of packets to have in "+
586 "one tile-part. 0 means include all packets in first tile-part "+
587 "of each tile","0"},
588 new string[] { "tiles", "<nominal tile width> <nominal tile height>",
589 "This option specifies the maximum tile dimensions to use. "+
590 "If both dimensions are 0 then no tiling is used.","0 0"},
591 new string[] { "ref", "<x> <y>",
592 "Sets the origin of the image in the canvas system. It sets the "+
593 "coordinate of the top-left corner of the image reference grid, "+
594 "with respect to the canvas origin","0 0"},
595 new string[] { "tref", "<x> <y>",
596 "Sets the origin of the tile partitioning on the reference grid, "+
597 "with respect to the canvas origin. The value of 'x' ('y') "+
598 "specified can not be larger than the 'x' one specified in the ref "+
599 "option.","0 0"},
600 new string[] { "rate", "<output bitrate in bpp>",
601 "This is the output bitrate of the codestream in bits per pixel."+
602 " When equal to -1, no image information (beside quantization "+
603 "effects) is discarded during compression.\n"+
604 "Note: In the case where '-file_format' option is used, the "+
605 "resulting file may have a larger bitrate.","-1"},
606 new string[] { "lossless", "[on|off]",
607 "Specifies a lossless compression for the encoder. This options"+
608 " is equivalent to use reversible quantization ('-Qtype "+
609 "reversible')"+
610 " and 5x3 wavelet filters pair ('-Ffilters w5x3'). Note that "+
611 "this option cannot be used with '-rate'. When this option is "+
612 "off, the quantization type and the filters pair is defined by "+
613 "'-Qtype' and '-Ffilters' respectively.","off"},
614 new string[] { "i", "<image file> [,<image file> [,<image file> ... ]]",
615 "Mandatory argument. This option specifies the name of the input "+
616 "image files. If several image files are provided, they have to be"+
617 " separated by commas in the command line. Supported formats are "+
618 "PGM (raw), PPM (raw) and PGX, "+
619 "which is a simple extension of the PGM file format for single "+
620 "component data supporting arbitrary bitdepths. If the extension "+
621 "is '.pgm', PGM-raw file format is assumed, if the extension is "+
622 "'.ppm', PPM-raw file format is assumed, otherwise PGX file "+
623 "format is assumed. PGM and PPM files are assumed to be 8 bits "+
624 "deep. A multi-component image can be specified by either "+
625 "specifying several PPM and/or PGX files, or by specifying one "+
626 "PPM file.",null},
627 new string[] { "o", "<file name>",
628 "Mandatory argument. This option specifies the name of the output "+
629 "file to which the codestream will be written.",null},
630 new string[] { "verbose", null,
631 "Prints information about the obtained bit stream.","on"},
632 new string[] { "v", "[on|off]",
633 "Prints version and copyright information.","off"},
634 new string[] { "u", "[on|off]",
635 "Prints usage information. "+
636 "If specified all other arguments (except 'v') are ignored","off"},
637 };
638 #endregion
639 }
640 }