JPEGCodec.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. //
  2. // System.Drawing.Imaging.JPEGCodec.cs
  3. //
  4. // Author:
  5. // Alexandre Pigolkine ([email protected])
  6. //
  7. // (C) 2002/2003 Ximian, Inc.
  8. #if DECLARE_CDECL_DELEGATES
  9. namespace cdeclCallback {
  10. using System;
  11. internal class cdeclRedirector {
  12. internal delegate void MethodVoidIntPtr(IntPtr param);
  13. internal delegate int MethodIntIntPtr(IntPtr param);
  14. internal delegate void MethodVoidIntPtrInt(IntPtr param, int param1);
  15. internal delegate int MethodIntIntPtrInt(IntPtr param,int param1);
  16. }
  17. }
  18. #endif
  19. namespace System.Drawing.Imaging
  20. {
  21. using System;
  22. using System.IO;
  23. using System.Drawing.Imaging;
  24. using System.Runtime.InteropServices;
  25. using cdeclCallback;
  26. /// <summary>
  27. /// Summary description for JPEGCodec.
  28. /// </summary>
  29. internal class JPEGCodec
  30. {
  31. enum J_COLOR_SPACE : int {
  32. JCS_UNKNOWN = 0, /* error/unspecified */
  33. JCS_GRAYSCALE = 1, /* monochrome */
  34. JCS_RGB = 2, /* red/green/blue */
  35. JCS_YCbCr = 3, /* Y/Cb/Cr (also known as YUV) */
  36. JCS_CMYK = 4, /* C/M/Y/K */
  37. JCS_YCCK = 5 /* Y/Cb/Cr/K */
  38. }
  39. [StructLayout(LayoutKind.Sequential)]
  40. internal struct jpeg_error_mgr_get {
  41. public IntPtr a1;
  42. public IntPtr a2;
  43. public IntPtr a3;
  44. public IntPtr a4;
  45. public IntPtr a5;
  46. public int msg_code;
  47. [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=20)]
  48. public int[] array;
  49. public int trace_level;
  50. public int num_warnings;
  51. public int jpeg_message_table;
  52. public int last_jpeg_message;
  53. public int addon_message_table;
  54. public int first_addon_message;
  55. public int last_addon_message;
  56. };
  57. [StructLayout(LayoutKind.Sequential)]
  58. internal struct jpeg_error_mgr {
  59. public cdeclRedirector.MethodVoidIntPtr error_exit;
  60. public IntPtr a2;
  61. public IntPtr a3;
  62. public IntPtr a4;
  63. public IntPtr a5;
  64. public int msg_code;
  65. [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=20)]
  66. public int[] array;
  67. public int trace_level;
  68. public int num_warnings;
  69. public int jpeg_message_table;
  70. public int last_jpeg_message;
  71. public int addon_message_table;
  72. public int first_addon_message;
  73. public int last_addon_message;
  74. };
  75. [StructLayout(LayoutKind.Sequential)]
  76. struct jpeg_source_mgr {
  77. public IntPtr next_input_byte; /* => next byte to read from buffer */
  78. public uint bytes_in_buffer; /* # of bytes remaining in buffer */
  79. //[MarshalAs(UnmanagedType.FunctionPtr)]
  80. public cdeclRedirector.MethodVoidIntPtr init_source;
  81. //[MarshalAs(UnmanagedType.FunctionPtr)]
  82. public cdeclRedirector.MethodIntIntPtr fill_input_buffer;
  83. //[MarshalAs(UnmanagedType.FunctionPtr)]
  84. public cdeclRedirector.MethodVoidIntPtrInt skip_input_data;
  85. //[MarshalAs(UnmanagedType.FunctionPtr)]
  86. public cdeclRedirector.MethodIntIntPtrInt resync_to_restart;
  87. //[MarshalAs(UnmanagedType.FunctionPtr)]
  88. public cdeclRedirector.MethodVoidIntPtr term_source;
  89. };
  90. class jpeg_decompress_struct {
  91. byte[] raw_struct;
  92. IntPtr raw_error_mgr = IntPtr.Zero;
  93. IntPtr raw_source_mgr = IntPtr.Zero;
  94. internal struct decompress_fields {
  95. internal int structure_size;
  96. internal int QUANTIZE_COLORS;
  97. internal int ACTUAL_NUMBER_OF_COLORS;
  98. internal int OUT_COLOR_SPACE;
  99. internal int OUTPUT_WIDTH;
  100. internal int OUTPUT_HEIGHT;
  101. internal int OUT_COLOR_COMPONENT;
  102. internal int OUTPUT_COMPONENTS;
  103. internal int OUTPUT_SCANLINE;
  104. internal int OUT_COLORMAP;
  105. };
  106. const int GNU_JPEG_DLL_WINDOWS = 0;
  107. const int LINUX_LIBJPEG = 1;
  108. const int KNOWN_JPEG_LINRARIES = 2;
  109. static bool offsets_initialized;
  110. static decompress_fields[] know_jpeg_libraries;
  111. static int current_library_index = LINUX_LIBJPEG;
  112. static void initialize_jpeg_decompress_structs() {
  113. if (!offsets_initialized) {
  114. know_jpeg_libraries = new decompress_fields[KNOWN_JPEG_LINRARIES];
  115. // GNU JPEG Windows version
  116. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].structure_size = 432;
  117. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].QUANTIZE_COLORS = 74;
  118. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].ACTUAL_NUMBER_OF_COLORS = 112;
  119. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUT_COLOR_SPACE = 44;
  120. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUTPUT_WIDTH = 92;
  121. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUTPUT_HEIGHT = 96;
  122. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUT_COLOR_COMPONENT = 100;
  123. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUTPUT_COMPONENTS = 104;
  124. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUTPUT_SCANLINE = 120;
  125. know_jpeg_libraries[GNU_JPEG_DLL_WINDOWS].OUT_COLORMAP = 116;
  126. // libjpeg Linux version
  127. know_jpeg_libraries[LINUX_LIBJPEG].structure_size = 464;
  128. know_jpeg_libraries[LINUX_LIBJPEG].QUANTIZE_COLORS = 84;
  129. know_jpeg_libraries[LINUX_LIBJPEG].ACTUAL_NUMBER_OF_COLORS = 132;
  130. know_jpeg_libraries[LINUX_LIBJPEG].OUT_COLOR_SPACE = 44;
  131. know_jpeg_libraries[LINUX_LIBJPEG].OUTPUT_WIDTH = 112;
  132. know_jpeg_libraries[LINUX_LIBJPEG].OUTPUT_HEIGHT = 116;
  133. know_jpeg_libraries[LINUX_LIBJPEG].OUT_COLOR_COMPONENT = 120;
  134. know_jpeg_libraries[LINUX_LIBJPEG].OUTPUT_COMPONENTS = 124;
  135. know_jpeg_libraries[LINUX_LIBJPEG].OUTPUT_SCANLINE = 140;
  136. know_jpeg_libraries[LINUX_LIBJPEG].OUT_COLORMAP = 136;
  137. offsets_initialized = true;
  138. }
  139. }
  140. static jpeg_decompress_struct() {
  141. initialize_jpeg_decompress_structs();
  142. }
  143. public jpeg_decompress_struct() {
  144. raw_struct = new byte[know_jpeg_libraries[current_library_index].structure_size];
  145. }
  146. public void switch_to_struct_size(int size) {
  147. if (raw_struct.Length == size) return;
  148. bool structureFound = false;
  149. for( int i = 0; i < KNOWN_JPEG_LINRARIES; i++) {
  150. if( know_jpeg_libraries[i].structure_size == size) {
  151. current_library_index = i;
  152. raw_struct = new byte[know_jpeg_libraries[current_library_index].structure_size];
  153. structureFound = true;
  154. break;
  155. }
  156. }
  157. if (!structureFound) throw new Exception("JPEG Codec cannot work with existing libjpeg");
  158. }
  159. public byte[] raw_decompress_struct {
  160. get {
  161. return raw_struct;
  162. }
  163. }
  164. unsafe protected void copyToStruct( int value, int offset) {
  165. fixed( byte* pd = raw_struct) {
  166. *((int*)(pd + offset)) = value;
  167. }
  168. }
  169. unsafe protected int copyFromStruct( int offset) {
  170. int result = 0;
  171. fixed( byte* pd = raw_struct) {
  172. result = *((int*)(pd + offset));
  173. }
  174. return result;
  175. }
  176. public jpeg_error_mgr jpeg_error_mgr {
  177. set {
  178. raw_error_mgr = Marshal.AllocHGlobal(Marshal.SizeOf(value));
  179. Marshal.StructureToPtr(value, raw_error_mgr, false);
  180. copyToStruct(raw_error_mgr.ToInt32(), 0);
  181. }
  182. }
  183. public jpeg_source_mgr jpeg_source_mgr {
  184. set {
  185. raw_source_mgr = Marshal.AllocHGlobal( Marshal.SizeOf(value));
  186. Marshal.StructureToPtr( value, raw_source_mgr, false);
  187. copyToStruct(raw_source_mgr.ToInt32(), 24);
  188. }
  189. }
  190. public int Stride {
  191. get {
  192. return OutputWidth * OutputComponents;
  193. }
  194. }
  195. public Color[] ColorMap {
  196. get {
  197. int actual_number_of_colors = copyFromStruct(know_jpeg_libraries[current_library_index].ACTUAL_NUMBER_OF_COLORS);
  198. IntPtr nativeMap = (IntPtr)copyFromStruct(know_jpeg_libraries[current_library_index].OUT_COLORMAP);
  199. Color[] map = new Color[actual_number_of_colors];
  200. if (nativeMap != IntPtr.Zero) {
  201. byte[] byteMap = new byte[OutColorComponents * actual_number_of_colors];
  202. Marshal.Copy( (IntPtr)Marshal.ReadInt32(nativeMap), byteMap, 0, byteMap.Length);
  203. }
  204. return map;
  205. }
  206. }
  207. public J_COLOR_SPACE OutColorSpace {
  208. get {
  209. return (J_COLOR_SPACE)copyFromStruct(know_jpeg_libraries[current_library_index].OUT_COLOR_SPACE);
  210. }
  211. set {
  212. copyToStruct((int)value,know_jpeg_libraries[current_library_index].OUT_COLOR_SPACE);
  213. }
  214. }
  215. public bool QuantizeColors {
  216. get {
  217. return raw_struct[know_jpeg_libraries[current_library_index].QUANTIZE_COLORS] != (byte)0 ? true : false;
  218. }
  219. set {
  220. raw_struct[know_jpeg_libraries[current_library_index].QUANTIZE_COLORS] = value ? (byte)1 : (byte)0;
  221. }
  222. }
  223. public int OutputWidth {
  224. get {
  225. return copyFromStruct(know_jpeg_libraries[current_library_index].OUTPUT_WIDTH);
  226. }
  227. }
  228. public int OutputHeight {
  229. get {
  230. return copyFromStruct(know_jpeg_libraries[current_library_index].OUTPUT_HEIGHT);
  231. }
  232. }
  233. public int OutColorComponents {
  234. get {
  235. return copyFromStruct(know_jpeg_libraries[current_library_index].OUT_COLOR_COMPONENT);
  236. }
  237. }
  238. public int OutputComponents {
  239. get {
  240. return copyFromStruct(know_jpeg_libraries[current_library_index].OUTPUT_COMPONENTS);
  241. }
  242. }
  243. public int OutputScanLine {
  244. get {
  245. return copyFromStruct(know_jpeg_libraries[current_library_index].OUTPUT_SCANLINE);
  246. }
  247. }
  248. }
  249. [StructLayout(LayoutKind.Sequential)]
  250. internal struct JSAMPARRAY {
  251. // FIXME: This code is not working on Mono(** ERROR **: Invalid IL code at...). Report a bug and change it later.
  252. //const int MAX_SCAN_LINES = 10;
  253. //[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=MAX_SCAN_LINES)]
  254. //internal IntPtr[] JSAMPLES;
  255. internal IntPtr JSAMPLE0;
  256. internal IntPtr JSAMPLE1;
  257. internal JSAMPARRAY(int len) {
  258. /*
  259. JSAMPLES = new IntPtr[MAX_SCAN_LINES];
  260. for (int i = 0; i < MAX_SCAN_LINES; i++) {
  261. JSAMPLES[i] = Marshal.AllocHGlobal(len);
  262. }
  263. */
  264. JSAMPLE0 = Marshal.AllocHGlobal(len);
  265. JSAMPLE1 = Marshal.AllocHGlobal(len);
  266. }
  267. internal void Dispose() {
  268. /*
  269. for (int i = 0; i < MAX_SCAN_LINES; i++) {
  270. Marshal.FreeHGlobal(JSAMPLES[i]);
  271. }
  272. */
  273. Marshal.FreeHGlobal(JSAMPLE0);
  274. Marshal.FreeHGlobal(JSAMPLE1);
  275. }
  276. }
  277. const string JPEGLibrary = "jpeg";
  278. [DllImport(JPEGLibrary, EntryPoint="jpeg_CreateDecompress", CallingConvention=CallingConvention.Cdecl)]
  279. internal static extern void jpeg_create_decompress(byte[] info, int version, int structure_size);
  280. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  281. internal static extern void jpeg_std_error(ref jpeg_error_mgr_get err_mgr);
  282. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  283. internal static extern int jpeg_read_header(byte[] cinfo, int condition);
  284. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  285. internal static extern void jpeg_calc_output_dimensions(byte[] cinfo);
  286. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  287. internal static extern int jpeg_start_decompress(byte[] cinfo);
  288. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  289. internal static extern int jpeg_read_scanlines(byte[] cinfo, ref JSAMPARRAY buffer, int num);
  290. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  291. internal static extern int jpeg_finish_decompress(byte[] cinfo);
  292. [DllImport(JPEGLibrary, CallingConvention=CallingConvention.Cdecl)]
  293. internal static extern void jpeg_destroy_decompress(byte[] cinfo);
  294. Stream fs;
  295. IntPtr buffer;
  296. int readSize = 4096;
  297. void init_source( IntPtr cinfo) {
  298. buffer = Marshal.AllocHGlobal(readSize);
  299. }
  300. int fill_input_buffer( IntPtr cinfo) {
  301. byte[] result = new byte[readSize];
  302. int readed = fs.Read(result, 0, readSize);
  303. Marshal.Copy(result, 0, buffer, readed);
  304. IntPtr srcAddr = (IntPtr)Marshal.ReadInt32(cinfo, 24);
  305. Marshal.WriteInt32(srcAddr, 0, buffer.ToInt32());
  306. Marshal.WriteInt32(srcAddr, 4, readed);
  307. return 1;
  308. }
  309. void skip_input_data( IntPtr cinfo, int num_bytes) {
  310. //byte[] result = new byte[num_bytes];
  311. //fs.Read(result, 0, num_bytes);
  312. fs.Seek(num_bytes, SeekOrigin.Current);
  313. }
  314. int resync_to_restart( IntPtr cinfo, int desired){
  315. return 0;
  316. }
  317. void term_source( IntPtr cinfo) {
  318. Marshal.AllocHGlobal(buffer);
  319. fs.Close();
  320. }
  321. class RetryInitializationException : Exception {
  322. int libraryStructureSize;
  323. public RetryInitializationException(int structureSize) {
  324. this.libraryStructureSize = structureSize;
  325. }
  326. public int LibraryStructureSize {
  327. get {
  328. return libraryStructureSize;
  329. }
  330. }
  331. }
  332. enum JPEGErrorCodes : int {
  333. JERR_BAD_STRUCT_SIZE = 21
  334. }
  335. void error_exit( IntPtr cinfo) {
  336. jpeg_error_mgr mgr = new jpeg_error_mgr();
  337. IntPtr err_raw = (IntPtr)Marshal.ReadInt32(cinfo, 0);
  338. mgr = (jpeg_error_mgr)Marshal.PtrToStructure(err_raw, mgr.GetType());
  339. if ( mgr.msg_code == (int)JPEGErrorCodes.JERR_BAD_STRUCT_SIZE) {
  340. throw new RetryInitializationException(mgr.array[0]);
  341. }
  342. throw new Exception();
  343. }
  344. internal JPEGCodec() {
  345. }
  346. internal static ImageCodecInfo CodecInfo {
  347. get {
  348. ImageCodecInfo info = new ImageCodecInfo();
  349. info.Flags = /*ImageCodecFlags.Encoder | */ ImageCodecFlags.Decoder | ImageCodecFlags.Builtin | ImageCodecFlags.SupportBitmap;
  350. info.FormatDescription = "JPEG file format";
  351. info.FormatID = System.Drawing.Imaging.ImageFormat.Jpeg.Guid;
  352. info.MimeType = "image/jpeg";
  353. info.Version = 1;
  354. byte[][] signaturePatterns = new byte[1][];
  355. signaturePatterns[0] = new byte[]{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00};
  356. info.SignaturePatterns = signaturePatterns;
  357. byte[][] signatureMasks = new byte[1][];
  358. signatureMasks[0] = new byte[]{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  359. info.SignatureMasks = signatureMasks;
  360. info.decode += new ImageCodecInfo.DecodeFromStream(JPEGCodec.DecodeDelegate);
  361. info.encode += new ImageCodecInfo.EncodeToStream(JPEGCodec.EncodeDelegate);
  362. return info;
  363. }
  364. }
  365. internal static void DecodeDelegate (Stream stream, InternalImageInfo info) {
  366. JPEGCodec jpeg = new JPEGCodec();
  367. jpeg.Decode (stream, info);
  368. }
  369. internal static void EncodeDelegate (Stream stream, InternalImageInfo info) {
  370. JPEGCodec jpeg = new JPEGCodec();
  371. jpeg.Encode (stream, info);
  372. }
  373. internal unsafe void switch_color_bytes( byte[] image) {
  374. fixed(byte* start = image) {
  375. byte *pb = start;
  376. byte t1;
  377. for( int ic = 0; ic < image.Length; ic +=3) {
  378. t1 = *pb;
  379. *(pb) = *(pb+2);
  380. *(pb+2) = t1;
  381. pb += 3;
  382. }
  383. }
  384. }
  385. internal bool Decode( Stream stream, InternalImageInfo info) {
  386. fs = stream;
  387. jpeg_error_mgr_get mgr = new jpeg_error_mgr_get();
  388. mgr.array = new int[20];
  389. jpeg_std_error( ref mgr);
  390. jpeg_error_mgr mgr_real = new jpeg_error_mgr();
  391. mgr_real.array = new int[20];
  392. mgr_real.error_exit = new cdeclCallback.cdeclRedirector.MethodVoidIntPtr(this.error_exit);
  393. mgr_real.msg_code = mgr.msg_code;
  394. mgr_real.a2 = mgr.a2;
  395. mgr_real.a3 = mgr.a3;
  396. mgr_real.a4 = mgr.a4;
  397. mgr_real.a5 = mgr.a5;
  398. mgr_real.trace_level = mgr.trace_level;
  399. mgr_real.num_warnings = mgr.num_warnings;
  400. mgr_real.last_jpeg_message = mgr.last_jpeg_message;
  401. mgr_real.first_addon_message = mgr.first_addon_message;
  402. mgr_real.last_addon_message = mgr.last_addon_message;
  403. mgr_real.jpeg_message_table = mgr.jpeg_message_table;
  404. jpeg_decompress_struct cinfo = new jpeg_decompress_struct();
  405. cinfo.jpeg_error_mgr = mgr_real;
  406. bool initializedOk = false;
  407. do {
  408. try {
  409. jpeg_create_decompress(cinfo.raw_decompress_struct, 62, cinfo.raw_decompress_struct.Length);
  410. initializedOk = true;
  411. }
  412. catch( RetryInitializationException ex) {
  413. initializedOk = false;
  414. cinfo.switch_to_struct_size(ex.LibraryStructureSize);
  415. cinfo.jpeg_error_mgr = mgr_real;
  416. }
  417. }while( !initializedOk);
  418. jpeg_source_mgr smgr = new jpeg_source_mgr();
  419. smgr.next_input_byte = IntPtr.Zero;
  420. smgr.bytes_in_buffer = 0;
  421. smgr.init_source = new cdeclRedirector.MethodVoidIntPtr(this.init_source);
  422. smgr.fill_input_buffer = new cdeclRedirector.MethodIntIntPtr(this.fill_input_buffer);
  423. smgr.skip_input_data = new cdeclRedirector.MethodVoidIntPtrInt(this.skip_input_data);
  424. smgr.resync_to_restart = new cdeclRedirector.MethodIntIntPtrInt(this.resync_to_restart);
  425. smgr.term_source = new cdeclRedirector.MethodVoidIntPtr(this.term_source);
  426. cinfo.jpeg_source_mgr = smgr;
  427. jpeg_read_header( cinfo.raw_decompress_struct, 1);
  428. jpeg_calc_output_dimensions(cinfo.raw_decompress_struct);
  429. jpeg_start_decompress(cinfo.raw_decompress_struct);
  430. int row_width = cinfo.Stride;
  431. while ((row_width & 3) != 0) row_width++;
  432. int pad_bytes = (row_width - cinfo.Stride);
  433. if (cinfo.OutColorSpace == J_COLOR_SPACE.JCS_RGB) {
  434. if (cinfo.QuantizeColors) {
  435. info.Format = PixelFormat.Format8bppIndexed;
  436. }
  437. else {
  438. info.Format = PixelFormat.Format24bppRgb;
  439. }
  440. }
  441. else {
  442. info.Format = PixelFormat.Format8bppIndexed;
  443. }
  444. info.Size = new Size(cinfo.OutputWidth,cinfo.OutputHeight);
  445. info.Stride = cinfo.Stride + pad_bytes;
  446. info.Palette = new ColorPalette(1, cinfo.ColorMap);
  447. info.RawImageBytes = new byte[(cinfo.OutputHeight) * (cinfo.Stride + pad_bytes)];
  448. JSAMPARRAY outbuf = new JSAMPARRAY(cinfo.Stride);
  449. int outputRow = 0;
  450. int outputIndex = info.RawImageBytes.Length - cinfo.Stride - pad_bytes;
  451. while (cinfo.OutputScanLine < cinfo.OutputHeight) {
  452. // FIXME: switch to the Length after fixing a run-time error
  453. int readed = jpeg_read_scanlines(cinfo.raw_decompress_struct, ref outbuf, 1 /*outbuf.JSAMPLES.Length*/);
  454. for (int i = 0; i < readed; i++) {
  455. // FIXME: switch to .JSAMPLES[i] after fixing a run-time error
  456. //Marshal.Copy(outbuf.JSAMPLES[i], info.RawImageBytes, outputIndex, cinfo.Stride);
  457. Marshal.Copy(outbuf.JSAMPLE0, info.RawImageBytes, outputIndex, cinfo.Stride);
  458. outputIndex -= cinfo.Stride + pad_bytes;
  459. outputRow++;
  460. }
  461. }
  462. // FIXME: analise count of color components here
  463. switch_color_bytes(info.RawImageBytes);
  464. jpeg_finish_decompress(cinfo.raw_decompress_struct);
  465. jpeg_destroy_decompress(cinfo.raw_decompress_struct);
  466. return true;
  467. }
  468. internal bool Encode( Stream stream, InternalImageInfo info) {
  469. return false;
  470. }
  471. }
  472. }