1 /*
2 Copyright (c) 2015-2021 Timur Gafarov
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 
6 Permission is hereby granted, free of charge, to any person or organization
7 obtaining a copy of the software and accompanying documentation covered by
8 this license (the "Software") to use, reproduce, display, distribute,
9 execute, and transmit the Software, and to prepare derivative works of the
10 Software, and to permit third-parties to whom the Software is furnished to
11 do so, all subject to the following:
12 
13 The copyright notices in the Software and this entire statement, including
14 the above license grant, this restriction and the following disclaimer,
15 must be included in all copies of the Software, in whole or in part, and
16 all derivative works of the Software, unless such copies or derivative
17 works are solely in the form of machine-executable object code generated by
18 a source language processor.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 */
28 
29 /**
30  * Decode JPEG images
31  *
32  * Copyright: Timur Gafarov 2015-2021.
33  * License: $(LINK2 boost.org/LICENSE_1_0.txt, Boost License 1.0).
34  * Authors: Timur Gafarov
35  */
36 module dlib.image.io.jpeg;
37 
38 import std.stdio;
39 import std.algorithm;
40 import std..string;
41 import std.traits;
42 import std.math;
43 import dlib.core.memory;
44 import dlib.core.stream;
45 import dlib.core.compound;
46 import dlib.core.bitio;
47 import dlib.container.array;
48 import dlib.filesystem.local;
49 import dlib.image.color;
50 import dlib.image.image;
51 
52 /*
53  * Simple JPEG decoder
54  *
55  * Limitations:
56  *  - Doesn't support progressive JPEG
57  *  - Doesn't perform chroma interpolation
58  *  - Doesn't read EXIF metadata
59  */
60 
61 // Uncomment this to see debug messages
62 //version = JPEGDebug;
63 
64 T readNumeric(T) (InputStream istrm, Endian endian = Endian.Little)
65 if (is(T == ubyte))
66 {
67     ubyte b;
68     istrm.readBytes(&b, 1);
69     return b;
70 }
71 
72 T readNumeric(T) (InputStream istrm, Endian endian = Endian.Little)
73 if (is(T == ushort))
74 {
75     union U16
76     {
77         ubyte[2] asBytes;
78         ushort asUshort;
79     }
80     U16 u16;
81     istrm.readBytes(u16.asBytes.ptr, 2);
82     version(LittleEndian)
83     {
84         if (endian == Endian.Big)
85             return u16.asUshort.swapEndian16;
86         else
87             return u16.asUshort;
88     }
89     else
90     {
91         if (endian == Endian.Little)
92             return u16.asUshort.swapEndian16;
93         else
94             return u16.asUshort;
95     }
96 }
97 
98 char[size] readChars(size_t size) (InputStream istrm)
99 {
100     char[size] chars;
101     istrm.readBytes(chars.ptr, size);
102     return chars;
103 }
104 
105 /*
106  * JPEG-related Huffman coding
107  */
108 
109 struct HuffmanCode
110 {
111     ushort bits;
112     ushort length;
113 
114     auto bitString()
115     {
116         return .bitString(bits, length);
117     }
118 }
119 
120 struct HuffmanTableEntry
121 {
122     HuffmanCode code;
123     ubyte value;
124 }
125 
126 Array!char bitString(T)(T n, uint len = 1) if (isIntegral!T)
127 {
128     Array!char arr;
129 
130     const int size = T.sizeof * 8;
131 
132     bool s = 0;
133     for (int a = 0; a < size; a++)
134     {
135         bool bit = n >> (size - 1);
136         if (bit)
137             s = 1;
138         if (s)
139         {
140             arr.append(bit + '0');
141         }
142         n <<= 1;
143     }
144 
145     while (arr.length < len)
146         arr.appendLeft('0');
147 
148     return arr;
149 }
150 
151 struct HuffmanTreeNode
152 {
153     HuffmanTreeNode* parent;
154     HuffmanTreeNode* left;
155     HuffmanTreeNode* right;
156     ubyte ch;
157     uint freq;
158     bool blank = true;
159 
160     this(
161         HuffmanTreeNode* leftNode,
162         HuffmanTreeNode* rightNode,
163         ubyte symbol,
164         uint frequency,
165         bool isBlank)
166     {
167         parent = null;
168         left = leftNode;
169         right = rightNode;
170 
171         if (left !is null)
172             left.parent = &this;
173         if (right !is null)
174             right.parent = &this;
175 
176         ch = symbol;
177         freq = frequency;
178         blank = isBlank;
179     }
180 
181     bool isLeaf()
182     {
183         return (left is null && right is null);
184     }
185 
186     void free()
187     {
188         if (left !is null)
189         {
190             left.free();
191             Delete(left);
192         }
193 
194         if (right !is null)
195         {
196             right.free();
197             Delete(right);
198         }
199     }
200 }
201 
202 HuffmanTreeNode* emptyNode()
203 {
204     return New!HuffmanTreeNode(null, null, cast(ubyte)0, 0, false);
205 }
206 
207 HuffmanTreeNode* treeFromTable(Array!(HuffmanTableEntry) table)
208 {
209     HuffmanTreeNode* root = emptyNode();
210 
211     foreach(i, v; table.data)
212         treeAddCode(root, v.code, v.value);
213 
214     return root;
215 }
216 
217 void treeAddCode(HuffmanTreeNode* root, HuffmanCode code, ubyte value)
218 {
219     HuffmanTreeNode* node = root;
220     auto bs = code.bitString;
221     foreach(bit; bs.data)
222     {
223         if (bit == '0')
224         {
225             if (node.left is null)
226             {
227                 node.left = emptyNode();
228                 node.left.parent = node;
229             }
230 
231             node = node.left;
232         }
233         else if (bit == '1')
234         {
235             if (node.right is null)
236             {
237                 node.right = emptyNode();
238                 node.right.parent = node;
239             }
240 
241             node = node.right;
242         }
243     }
244     assert (node !is null);
245     node.ch = value;
246     bs.free();
247 }
248 
249 /*
250  * JPEG-related data types
251  */
252 
253 enum JPEGMarkerType
254 {
255     Unknown,
256     SOI,
257     SOF0,
258     SOF1,
259     SOF2,
260     DHT,
261     DQT,
262     DRI,
263     SOS,
264     RSTn,
265     APP0,
266     APPn,
267     COM,
268     EOI
269 }
270 
271 struct JPEGImage
272 {
273     struct JFIF
274     {
275         ubyte versionMajor;
276         ubyte versionMinor;
277         ubyte units;
278         ushort xDensity;
279         ushort yDensity;
280         ubyte thumbnailWidth;
281         ubyte thumbnailHeight;
282         ubyte[] thumbnail;
283 
284         void free()
285         {
286             if (thumbnail.length)
287                 Delete(thumbnail);
288         }
289     }
290 
291     struct DQT
292     {
293         ubyte precision;
294         ubyte tableId;
295         ubyte[] table;
296 
297         void free()
298         {
299             if (table.length)
300                 Delete(table);
301         }
302     }
303 
304     struct SOF0Component
305     {
306         ubyte hSubsampling;
307         ubyte vSubsampling;
308         ubyte dqtTableId;
309     }
310 
311     struct SOF0
312     {
313         ubyte precision;
314         ushort height;
315         ushort width;
316         ubyte componentsNum;
317         SOF0Component[] components;
318 
319         void free()
320         {
321             if (components.length)
322                 Delete(components);
323         }
324     }
325 
326     struct DHT
327     {
328         ubyte clas;
329         ubyte tableId;
330         Array!HuffmanTableEntry huffmanTable;
331         HuffmanTreeNode* huffmanTree;
332 
333         void free()
334         {
335             huffmanTree.free();
336             Delete(huffmanTree);
337             huffmanTable.free();
338         }
339     }
340 
341     struct SOSComponent
342     {
343         ubyte tableIdDC;
344         ubyte tableIdAC;
345     }
346 
347     struct SOS
348     {
349         ubyte componentsNum;
350         SOSComponent[] components;
351         ubyte spectralSelectionStart;
352         ubyte spectralSelectionEnd;
353         ubyte successiveApproximationBitHigh;
354         ubyte successiveApproximationBitLow;
355 
356         void free()
357         {
358             if (components.length)
359                 Delete(components);
360         }
361     }
362 
363     JFIF jfif;
364     DQT[] dqt;
365     SOF0 sof0;
366     DHT[] dht;
367     SOS sos;
368 
369     DQT* addDQT()
370     {
371         if (dqt.length > 0)
372             reallocateArray(dqt, dqt.length+1);
373         else
374             dqt = New!(DQT[])(1);
375         return &dqt[$-1];
376     }
377 
378     DHT* addDHT()
379     {
380         if (dht.length > 0)
381             reallocateArray(dht, dht.length+1);
382         else
383             dht = New!(DHT[])(1);
384         return &dht[$-1];
385     }
386 
387     void free()
388     {
389         jfif.free();
390         foreach(ref t; dqt) t.free();
391         if (dqt.length)
392             Delete(dqt);
393         sof0.free();
394         foreach(ref t; dht) t.free();
395         if (dht.length)
396             Delete(dht);
397         sos.free();
398     }
399 
400     DQT* getQuantizationTable(ubyte id)
401     {
402         foreach(ref t; dqt)
403             if (t.tableId == id)
404                 return &t;
405         return null;
406     }
407 
408     DHT* getHuffmanTable(ubyte clas, ubyte id)
409     {
410         foreach(ref t; dht)
411             if (t.clas == clas &&
412                 t.tableId == id)
413                 return &t;
414         return null;
415     }
416 }
417 
418 /**
419  * Load JPEG from file using local FileSystem.
420  * Causes GC allocation
421  */
422 SuperImage loadJPEG(string filename)
423 {
424     InputStream input = openForInput(filename);
425     auto img = loadJPEG(input);
426     input.close();
427     return img;
428 }
429 
430 /**
431  * Load JPEG from stream using default image factory.
432  * Causes GC allocation
433  */
434 SuperImage loadJPEG(InputStream istrm)
435 {
436     Compound!(SuperImage, string) res =
437         loadJPEG(istrm, defaultImageFactory);
438     if (res[0] is null)
439         throw new Exception(res[1]);
440     else
441         return res[0];
442 }
443 
444 /**
445  * Load JPEG from stream using specified image factory.
446  * GC-free
447  */
448 Compound!(SuperImage, string) loadJPEG(
449     InputStream istrm,
450     SuperImageFactory imgFac)
451 {
452     JPEGImage jpg;
453     SuperImage img = null;
454 
455     while (istrm.readable)
456     {
457         JPEGMarkerType mt;
458         auto res = readMarker(&jpg, istrm, &mt);
459         if (res[0])
460         {
461             // TODO: add progressive JPEG support
462             if (mt == JPEGMarkerType.SOF2)
463             {
464                 jpg.free();
465                 return compound(img, "loadJPEG error: progressive JPEG is not supported");
466             }
467             else if (mt == JPEGMarkerType.SOS)
468                 break;
469         }
470         else
471         {
472             jpg.free();
473             return compound(img, res[1]);
474         }
475     }
476     auto res = decodeScanData(&jpg, istrm, imgFac);
477     jpg.free();
478     return res;
479 }
480 
481 /*
482  *  Decode marker from JPEG stream
483  */
484 Compound!(bool, string) readMarker(
485     JPEGImage* jpg,
486     InputStream istrm,
487     JPEGMarkerType* mt)
488 {
489     ushort magic = istrm.readNumeric!ushort(Endian.Big);
490 
491     switch (magic)
492     {
493         case 0xFFD8:
494             *mt = JPEGMarkerType.SOI;
495             version(JPEGDebug) writeln("SOI");
496             break;
497 
498         case 0xFFE0:
499             *mt = JPEGMarkerType.APP0;
500             return readJFIF(jpg, istrm);
501 
502         case 0xFFE1:
503             *mt = JPEGMarkerType.APPn;
504             return readAPPn(jpg, istrm, 1);
505 
506         case 0xFFE2:
507             *mt = JPEGMarkerType.APPn;
508             return readAPPn(jpg, istrm, 2);
509 
510         case 0xFFE3:
511             *mt = JPEGMarkerType.APPn;
512             return readAPPn(jpg, istrm, 3);
513 
514         case 0xFFE4:
515             *mt = JPEGMarkerType.APPn;
516             return readAPPn(jpg, istrm, 4);
517 
518         case 0xFFE5:
519             *mt = JPEGMarkerType.APPn;
520             return readAPPn(jpg, istrm, 5);
521 
522         case 0xFFE6:
523             *mt = JPEGMarkerType.APPn;
524             return readAPPn(jpg, istrm, 6);
525 
526         case 0xFFE7:
527             *mt = JPEGMarkerType.APPn;
528             return readAPPn(jpg, istrm, 7);
529 
530         case 0xFFE8:
531             *mt = JPEGMarkerType.APPn;
532             return readAPPn(jpg, istrm, 8);
533 
534          case 0xFFE9:
535             *mt = JPEGMarkerType.APPn;
536             return readAPPn(jpg, istrm, 9);
537 
538          case 0xFFEA:
539             *mt = JPEGMarkerType.APPn;
540             return readAPPn(jpg, istrm, 10);
541 
542          case 0xFFEB:
543             *mt = JPEGMarkerType.APPn;
544             return readAPPn(jpg, istrm, 11);
545 
546          case 0xFFEC:
547             *mt = JPEGMarkerType.APPn;
548             return readAPPn(jpg, istrm, 12);
549 
550          case 0xFFED:
551             *mt = JPEGMarkerType.APPn;
552             return readAPPn(jpg, istrm, 13);
553 
554          case 0xFFEE:
555             *mt = JPEGMarkerType.APPn;
556             return readAPPn(jpg, istrm, 14);
557 
558          case 0xFFEF:
559             *mt = JPEGMarkerType.APPn;
560             return readAPPn(jpg, istrm, 15);
561 
562         case 0xFFDB:
563             *mt = JPEGMarkerType.DQT;
564             return readDQT(jpg, istrm);
565 
566         case 0xFFC0:
567             *mt = JPEGMarkerType.SOF0;
568             return readSOF0(jpg, istrm);
569 
570         case 0xFFC2:
571             *mt = JPEGMarkerType.SOF2;
572             break;
573 
574         case 0xFFC4:
575             *mt = JPEGMarkerType.DHT;
576             return readDHT(jpg, istrm);
577 
578         case 0xFFDA:
579             *mt = JPEGMarkerType.SOS;
580             return readSOS(jpg, istrm);
581 
582         case 0xFFFE:
583             *mt = JPEGMarkerType.COM;
584             return readCOM(jpg, istrm);
585 
586         default:
587             *mt = JPEGMarkerType.Unknown;
588             break;
589     }
590 
591     return compound(true, "");
592 }
593 
594 Compound!(bool, string) readJFIF(JPEGImage* jpg, InputStream istrm)
595 {
596     ushort jfif_length = istrm.readNumeric!ushort(Endian.Big);
597 
598     char[5] jfif_id = istrm.readChars!5;
599     if (jfif_id != "JFIF\0")
600         return compound(false, "loadJPEG error: illegal JFIF header");
601 
602     jpg.jfif.versionMajor = istrm.readNumeric!ubyte;
603     jpg.jfif.versionMinor = istrm.readNumeric!ubyte;
604     jpg.jfif.units = istrm.readNumeric!ubyte;
605     jpg.jfif.xDensity = istrm.readNumeric!ushort(Endian.Big);
606     jpg.jfif.yDensity = istrm.readNumeric!ushort(Endian.Big);
607     jpg.jfif.thumbnailWidth = istrm.readNumeric!ubyte;
608     jpg.jfif.thumbnailHeight = istrm.readNumeric!ubyte;
609 
610     uint jfif_thumb_length = jpg.jfif.thumbnailWidth * jpg.jfif.thumbnailHeight * 3;
611     if (jfif_thumb_length > 0)
612     {
613         jpg.jfif.thumbnail = New!(ubyte[])(jfif_thumb_length);
614         istrm.readBytes(jpg.jfif.thumbnail.ptr, jfif_thumb_length);
615     }
616 
617     version(JPEGDebug)
618     {
619         writefln("APP0/JFIF length: %s", jfif_length);
620         writefln("APP0/JFIF identifier: %s", jfif_id);
621         writefln("APP0/JFIF version major: %s", jpg.jfif.versionMajor);
622         writefln("APP0/JFIF version minor: %s", jpg.jfif.versionMinor);
623         writefln("APP0/JFIF units: %s", jpg.jfif.units);
624         writefln("APP0/JFIF xdensity: %s", jpg.jfif.xDensity);
625         writefln("APP0/JFIF ydensity: %s", jpg.jfif.yDensity);
626         writefln("APP0/JFIF xthumbnail: %s", jpg.jfif.thumbnailWidth);
627         writefln("APP0/JFIF ythumbnail: %s", jpg.jfif.thumbnailHeight);
628     }
629 
630     return compound(true, "");
631 }
632 
633 /*
634  * APP1 - EXIF, XMP, ExtendedXMP, QVCI, FLIR
635  * APP2 - ICC, FPXR, MPF, PreviewImage
636  * APP3 - Kodak Meta, Stim, PreviewImage
637  * APP4 - Scalado, FPXR, PreviewImage
638  * APP5 - RMETA, PreviewImage
639  * APP6 - EPPIM, NITF, HP TDHD
640  * APP7 - Pentax, Qualcomm
641  * APP8 - SPIFF
642  * APP9 - MediaJukebox
643  * APP10 - PhotoStudio comment
644  * APP11 - JPEG-HDR
645  * APP12 - PictureInfo, Ducky
646  * APP13 - Photoshop, Adobe CM
647  * APP14 - Adobe
648  * APP15 - GraphicConverter
649  */
650 Compound!(bool, string) readAPPn(JPEGImage* jpg, InputStream istrm, uint n)
651 {
652     ushort app_length = istrm.readNumeric!ushort(Endian.Big);
653     ubyte[] app = New!(ubyte[])(app_length-2);
654     istrm.readBytes(app.ptr, app_length-2);
655 
656     // TODO: interpret APP data (EXIF etc.) and save it somewhere.
657     // Maybe add a generic ImageInfo object for this?
658     Delete(app);
659 
660     version(JPEGDebug)
661     {
662         writefln("APP%s length: %s", n, app_length);
663     }
664 
665     return compound(true, "");
666 }
667 
668 Compound!(bool, string) readCOM(JPEGImage* jpg, InputStream istrm)
669 {
670     ushort com_length = istrm.readNumeric!ushort(Endian.Big);
671     ubyte[] com = New!(ubyte[])(com_length-2);
672     istrm.readBytes(com.ptr, com_length-2);
673 
674     version(JPEGDebug)
675     {
676         writefln("COM string: \"%s\"", cast(string)com);
677         writefln("COM length: %s", com_length);
678     }
679 
680     // TODO: save COM data somewhere.
681     // Maybe add a generic ImageInfo object for this?
682     Delete(com);
683 
684     return compound(true, "");
685 }
686 
687 Compound!(bool, string) readDQT(JPEGImage* jpg, InputStream istrm)
688 {
689     ushort dqt_length = istrm.readNumeric!ushort(Endian.Big);
690     version(JPEGDebug)
691     {
692         writefln("DQT length: %s", dqt_length);
693     }
694 
695     dqt_length -= 2;
696 
697     while(dqt_length)
698     {
699         JPEGImage.DQT* dqt = jpg.addDQT();
700 
701         ubyte bite = istrm.readNumeric!ubyte;
702         dqt.precision = bite.hiNibble;
703         dqt.tableId = bite.loNibble;
704 
705         dqt_length--;
706 
707         if (dqt.precision == 0)
708         {
709             dqt.table = New!(ubyte[])(64);
710             dqt_length -= 64;
711         }
712         else if (dqt.precision == 1)
713         {
714             dqt.table = New!(ubyte[])(128);
715             dqt_length -= 128;
716         }
717 
718         istrm.readBytes(dqt.table.ptr, dqt.table.length);
719 
720         version(JPEGDebug)
721         {
722             writefln("DQT precision: %s", dqt.precision);
723             writefln("DQT table id: %s", dqt.tableId);
724             writefln("DQT table: %s", dqt.table);
725         }
726     }
727 
728     return compound(true, "");
729 }
730 
731 Compound!(bool, string) readSOF0(JPEGImage* jpg, InputStream istrm)
732 {
733     ushort sof0_length = istrm.readNumeric!ushort(Endian.Big);
734     jpg.sof0.precision = istrm.readNumeric!ubyte;
735     jpg.sof0.height = istrm.readNumeric!ushort(Endian.Big);
736     jpg.sof0.width = istrm.readNumeric!ushort(Endian.Big);
737     jpg.sof0.componentsNum = istrm.readNumeric!ubyte;
738 
739     version(JPEGDebug)
740     {
741         writefln("SOF0 length: %s", sof0_length);
742         writefln("SOF0 precision: %s", jpg.sof0.precision);
743         writefln("SOF0 height: %s", jpg.sof0.height);
744         writefln("SOF0 width: %s", jpg.sof0.width);
745         writefln("SOF0 components: %s", jpg.sof0.componentsNum);
746     }
747 
748     jpg.sof0.components = New!(JPEGImage.SOF0Component[])(jpg.sof0.componentsNum);
749 
750     foreach(ref c; jpg.sof0.components)
751     {
752         ubyte c_id = istrm.readNumeric!ubyte;
753         ubyte bite = istrm.readNumeric!ubyte;
754         c.hSubsampling = bite.hiNibble;
755         c.vSubsampling = bite.loNibble;
756         c.dqtTableId = istrm.readNumeric!ubyte;
757         version(JPEGDebug)
758         {
759             writefln("SOF0 component id: %s", c_id);
760             writefln("SOF0 component %s hsubsampling: %s", c_id, c.hSubsampling);
761             writefln("SOF0 component %s vsubsampling: %s", c_id, c.vSubsampling);
762             writefln("SOF0 component %s table id: %s", c_id, c.dqtTableId);
763         }
764     }
765 
766     return compound(true, "");
767 }
768 
769 Compound!(bool, string) readDHT(JPEGImage* jpg, InputStream istrm)
770 {
771     ushort dht_length = istrm.readNumeric!ushort(Endian.Big);
772     version(JPEGDebug)
773     {
774         writefln("DHT length: %s", dht_length);
775     }
776 
777     dht_length -= 2;
778 
779     while(dht_length > 0)
780     {
781         JPEGImage.DHT* dht = jpg.addDHT();
782 
783         ubyte bite = istrm.readNumeric!ubyte;
784         dht_length--;
785         dht.clas = bite.hiNibble;
786         dht.tableId = bite.loNibble;
787 
788         ubyte[16] dht_code_lengths;
789         istrm.readBytes(dht_code_lengths.ptr, 16);
790         dht_length -= 16;
791 
792         version(JPEGDebug)
793         {
794             writefln("DHT class: %s (%s)",
795                 dht.clas,
796                 dht.clas? "AC":"DC");
797             writefln("DHT tableId: %s", dht.tableId);
798             writefln("DHT Huffman code lengths: %s", dht_code_lengths);
799         }
800 
801         // Read Huffman table
802         int totalCodes = reduce!("a + b")(0, dht_code_lengths);
803         int storedCodes = 0;
804         ubyte treeLevel = 0;
805         ushort bits = 0;
806 
807         while (storedCodes != totalCodes)
808         {
809             while (treeLevel < 15 &&
810                 dht_code_lengths[treeLevel] == 0)
811             {
812                 treeLevel++;
813                 bits *= 2;
814             }
815 
816             if (treeLevel < 16)
817             {
818                 uint bitsNum = treeLevel + 1;
819                 HuffmanCode code = HuffmanCode(bits, cast(ushort)bitsNum);
820 
821                 auto entry = HuffmanTableEntry(code, istrm.readNumeric!ubyte);
822                 dht.huffmanTable.append(entry);
823 
824                 dht_length--;
825 
826                 storedCodes++;
827                 bits++;
828                 dht_code_lengths[treeLevel]--;
829             }
830         }
831 
832         dht.huffmanTree = treeFromTable(dht.huffmanTable);
833     }
834 
835     return compound(true, "");
836 }
837 
838 Compound!(bool, string) readSOS(JPEGImage* jpg, InputStream istrm)
839 {
840     ushort sos_length = istrm.readNumeric!ushort(Endian.Big);
841     jpg.sos.componentsNum = istrm.readNumeric!ubyte;
842 
843     version(JPEGDebug)
844     {
845         writefln("SOS length: %s", sos_length);
846         writefln("SOS components: %s", jpg.sos.componentsNum);
847     }
848 
849     jpg.sos.components = New!(JPEGImage.SOSComponent[])(jpg.sos.componentsNum);
850 
851     foreach(ref c; jpg.sos.components)
852     {
853         ubyte c_id = istrm.readNumeric!ubyte;
854         ubyte bite = istrm.readNumeric!ubyte;
855         c.tableIdDC = bite.hiNibble;
856         c.tableIdAC = bite.loNibble;
857         version(JPEGDebug)
858         {
859             writefln("SOS component id: %s", c_id);
860             writefln("SOS component %s DC table id: %s", c_id, c.tableIdDC);
861             writefln("SOS component %s AC table id: %s", c_id, c.tableIdAC);
862         }
863     }
864 
865     jpg.sos.spectralSelectionStart = istrm.readNumeric!ubyte;
866     jpg.sos.spectralSelectionEnd = istrm.readNumeric!ubyte;
867     ubyte bite = istrm.readNumeric!ubyte;
868     jpg.sos.successiveApproximationBitHigh = bite.hiNibble;
869     jpg.sos.successiveApproximationBitLow = bite.loNibble;
870 
871     version(JPEGDebug)
872     {
873         writefln("SOS spectral selection start: %s", jpg.sos.spectralSelectionStart);
874         writefln("SOS spectral selection end: %s", jpg.sos.spectralSelectionEnd);
875         writefln("SOS successive approximation bit: %s", jpg.sos.successiveApproximationBitHigh);
876         writefln("SOS successive approximation bit low: %s", jpg.sos.successiveApproximationBitLow);
877     }
878 
879     return compound(true, "");
880 }
881 
882 struct ScanBitStream
883 {
884     InputStream istrm;
885 
886     bool endMarkerFound = false;
887     uint bytesRead = 0;
888     ubyte prevByte = 0x00;
889     ubyte curByte = 0x00;
890 
891     ubyte readNextByte()
892     {
893         ubyte b = istrm.readNumeric!ubyte;
894         bytesRead++;
895         endMarkerFound = (prevByte == 0xFF && b == 0xD9);
896         assert(!endMarkerFound);
897         if (!endMarkerFound)
898         {
899             prevByte = b;
900             curByte = b;
901             return b;
902         }
903         else
904         {
905             curByte = 0;
906         }
907         return curByte;
908     }
909 
910     bool readable()
911     {
912         return !istrm.readable || endMarkerFound;
913     }
914 
915     uint bitPos = 0;
916 
917     // Huffman decode a byte
918     Compound!(bool, string) decodeByte(HuffmanTreeNode* node, ubyte* result)
919     {
920         while(!node.isLeaf)
921         {
922             ubyte b = curByte;
923 
924             bool bit = getBit(b, 7-bitPos);
925             bitPos++;
926             if (bitPos == 8)
927             {
928                 bitPos = 0;
929                 readNextByte();
930 
931                 if (b == 0xFF)
932                 {
933                     b = curByte;
934                     if (b == 0x00)
935                     {
936                         readNextByte();
937                     }
938                 }
939             }
940 
941             if (bit)
942                 node = node.right;
943             else
944                 node = node.left;
945 
946             if (node is null)
947                 return compound(false, "loadJPEG error: no Huffman code found");
948         }
949 
950         *result = node.ch;
951         return compound(true, "");
952     }
953 
954     // Read len bits from stream to buffer
955     uint readBits(ubyte len)
956     {
957         uint buffer = 0;
958         uint i = 0;
959         uint by = 0;
960         uint bi = 0;
961 
962         while (i < len)
963         {
964             ubyte b = curByte;
965 
966             bool bit = getBit(b, 7-bitPos);
967             buffer = setBit(buffer, (by * 8 + bi), bit);
968 
969             bi++;
970             if (bi == 8)
971             {
972                 bi = 0;
973                 by++;
974             }
975 
976             i++;
977 
978             bitPos++;
979             if (bitPos == 8)
980             {
981                 bitPos = 0;
982                 readNextByte();
983 
984                 if (b == 0xFF)
985                 {
986                     b = curByte;
987                     if (b == 0x00)
988                         readNextByte();
989                 }
990             }
991         }
992 
993         return buffer;
994     }
995 }
996 
997 /*
998  *  Decodes compressed data and creates RGB image from it
999  */
1000 Compound!(SuperImage, string) decodeScanData(
1001     JPEGImage* jpg,
1002     InputStream istrm,
1003     SuperImageFactory imgFac)
1004 {
1005     SuperImage img = imgFac.createImage(jpg.sof0.width, jpg.sof0.height, 3, 8);
1006 
1007     MCU mcu;
1008     foreach(ci, ref c; jpg.sof0.components)
1009     {
1010         if (ci == 0)
1011             mcu.createYBlocks(c.hSubsampling, c.vSubsampling);
1012         else if (ci == 1)
1013             mcu.createCbBlocks(c.hSubsampling, c.vSubsampling);
1014         else if (ci == 2)
1015             mcu.createCrBlocks(c.hSubsampling, c.vSubsampling);
1016     }
1017 
1018     Compound!(SuperImage, string) error(string errorMsg)
1019     {
1020         mcu.free();
1021         if (img)
1022         {
1023             img.free();
1024             img = null;
1025         }
1026         return compound(img, errorMsg);
1027     }
1028 
1029     // Decode DCT coefficient from bit buffer
1030     int decodeCoef(uint buffer, ubyte numBits)
1031     {
1032         bool positive = getBit(buffer, 0);
1033 
1034         int value = 0;
1035         foreach(j; 0..numBits)
1036         {
1037             bool bit = getBit(buffer, numBits-1-j);
1038             value = setBit(value, j, bit);
1039         }
1040 
1041         if (positive)
1042             return value;
1043         else
1044             return value - 2^^numBits + 1;
1045     }
1046 
1047     static const ubyte[64] dezigzag =
1048     [
1049          0,  1,  8, 16,  9,  2,  3, 10,
1050         17, 24, 32, 25, 18, 11,  4,  5,
1051         12, 19, 26, 33, 40, 48, 41, 34,
1052         27, 20, 13,  6,  7, 14, 21, 28,
1053         35, 42, 49, 56, 57, 50, 43, 36,
1054         29, 22, 15, 23, 30, 37, 44, 51,
1055         58, 59, 52, 45, 38, 31, 39, 46,
1056         53, 60, 61, 54, 47, 55, 62, 63
1057     ];
1058 
1059     if (jpg.sos.componentsNum != 3)
1060     {
1061         return error(format(
1062                 "loadJPEG error: unsupported number of components: %s",
1063                 jpg.sos.componentsNum));
1064     }
1065 
1066     // Store previous DC coefficients
1067     int[3] dcCoefPrev;
1068 
1069     if (jpg.dqt.length == 0)
1070         return error("loadJPEG error: no DQTs found");
1071 
1072     ScanBitStream sbs;
1073     sbs.endMarkerFound = false;
1074     sbs.bytesRead = 0;
1075     sbs.prevByte = 0x00;
1076     sbs.curByte = 0x00;
1077     sbs.istrm = istrm;
1078     sbs.readNextByte();
1079 
1080     uint numMCUsH = jpg.sof0.width / mcu.width + ((jpg.sof0.width % mcu.width) > 0);
1081     uint numMCUsV = jpg.sof0.height / mcu.height + ((jpg.sof0.height % mcu.height) > 0);
1082 
1083     // Read MCUs
1084     foreach(mcuY; 0..numMCUsV)
1085     foreach(mcuX; 0..numMCUsH)
1086     {
1087         // Read MCU for each channel
1088         foreach(ci, ref c; jpg.sos.components)
1089         {
1090             auto tableDC = jpg.getHuffmanTable(0, c.tableIdDC);
1091             auto tableAC = jpg.getHuffmanTable(1, c.tableIdAC);
1092 
1093             if (tableDC is null)
1094                 return error("loadJPEG error: illegal DC table index in MCU component");
1095             if (tableAC is null)
1096                 return error("loadJPEG error: illegal AC table index in MCU component");
1097 
1098             auto component = jpg.sof0.components[ci];
1099             auto hblocks = component.hSubsampling;
1100             auto vblocks = component.vSubsampling;
1101             auto dqtTableId = component.dqtTableId;
1102             if (dqtTableId >= jpg.dqt.length)
1103                 return error("loadJPEG error: illegal DQT table index in MCU component");
1104 
1105             // Read 8x8 blocks
1106             foreach(by; 0..vblocks)
1107             foreach(bx; 0..hblocks)
1108             {
1109                 int[8*8] block;
1110 
1111                 // Read DC coefficient
1112                 ubyte dcDiffLen;
1113                 auto res = sbs.decodeByte(tableDC.huffmanTree, &dcDiffLen);
1114                 if (!res[0]) return error(res[1]);
1115 
1116                 if (dcDiffLen > 0)
1117                 {
1118                     uint dcBuffer = sbs.readBits(dcDiffLen);
1119                     dcCoefPrev[ci] += decodeCoef(dcBuffer, dcDiffLen);
1120                 }
1121 
1122                 block[0] = dcCoefPrev[ci];
1123 
1124                 // Read AC coefficients
1125                 {
1126                     uint i = 1;
1127                     bool eob = false;
1128                     while (!eob && i < 64)
1129                     {
1130                         ubyte code;
1131                         res = sbs.decodeByte(tableAC.huffmanTree, &code);
1132                         if (!res[0]) return error(res[1]);
1133 
1134                         if (code == 0x00) // EOB, all next values are zero
1135                             eob = true;
1136                         else if (code == 0xF0) // ZRL, next 16 values are zero
1137                         {
1138                             foreach(j; 0..16)
1139                             if (i < 64)
1140                             {
1141                                 block[i] = 0;
1142                                 i++;
1143                             }
1144                         }
1145                         else
1146                         {
1147                             ubyte hi = hiNibble(code);
1148                             ubyte lo = loNibble(code);
1149 
1150                             uint zeroes = hi;
1151                             foreach(j; 0..zeroes)
1152                             if (i < 64)
1153                             {
1154                                 block[i] = 0;
1155                                 i++;
1156                             }
1157 
1158                             int acCoef = 0;
1159                             if (lo > 0)
1160                             {
1161                                 uint acBuffer = sbs.readBits(lo);
1162                                 acCoef = decodeCoef(acBuffer, lo);
1163                             }
1164 
1165                             if (i < 64)
1166                                 block[i] = acCoef;
1167 
1168                             i++;
1169                         }
1170                     }
1171                 }
1172 
1173                 // Multiply block by quantization matrix
1174                 foreach(i, ref v; block)
1175                     v *= jpg.dqt[dqtTableId].table[i];
1176 
1177                 // Convert matrix from zig-zag order to normal order
1178                 int[8*8] dctMatrix;
1179 
1180                 foreach(i, v; block)
1181                     dctMatrix[dezigzag[i]] = v;
1182 
1183                 idct64(dctMatrix.ptr);
1184 
1185                 // Copy the matrix into corresponding channel
1186                 int* outMatrixPtr;
1187                 if (ci == 0)
1188                     outMatrixPtr = mcu.yBlocks[by * hblocks + bx].ptr;
1189                 else if (ci == 1)
1190                     outMatrixPtr = mcu.cbBlocks[by * hblocks + bx].ptr;
1191                 else if (ci == 2)
1192                     outMatrixPtr = mcu.crBlocks[by * hblocks + bx].ptr;
1193                 else
1194                     return error("loadJPEG error: illegal component index");
1195 
1196                 for(uint i = 0; i < 64; i++)
1197                     outMatrixPtr[i] = dctMatrix[i];
1198             }
1199         }
1200 
1201         // Convert MCU from YCbCr to RGB
1202         foreach(y; 0..mcu.height) // Pixel coordinates in MCU
1203         foreach(x; 0..mcu.width)
1204         {
1205             Color4f col = mcu.getPixel(x, y);
1206 
1207             // Pixel coordinates in image
1208             uint ix = mcuX * mcu.width + x;
1209             uint iy = mcuY * mcu.height + y;
1210 
1211             if (ix < img.width && iy < img.height)
1212                 img[ix, iy] = col;
1213         }
1214     }
1215 
1216     version(JPEGDebug)
1217     {
1218         writefln("Bytes read: %s", sbs.bytesRead);
1219     }
1220 
1221     mcu.free();
1222 
1223     return compound(img, "");
1224 }
1225 
1226 /*
1227  * MCU struct keeps a storage for one Minimal Code Unit
1228  * and provides a generalized interface for decoding
1229  * images with different subsampling modes.
1230  * Decoder should read 8x8 blocks one by one for each channel
1231  * and fill corresponding arrays in MCU.
1232  */
1233 struct MCU
1234 {
1235     uint width;
1236     uint height;
1237 
1238     alias Block = int[8*8];
1239     Block[] yBlocks;
1240     Block[] cbBlocks;
1241     Block[] crBlocks;
1242 
1243     uint ySamplesH, ySamplesV;
1244     uint cbSamplesH, cbSamplesV;
1245     uint crSamplesH, crSamplesV;
1246 
1247     uint yWidth, yHeight;
1248     uint cbWidth, cbHeight;
1249     uint crWidth, crHeight;
1250 
1251     void createYBlocks(uint hsubsampling, uint vsubsampling)
1252     {
1253         yBlocks = New!(Block[])(hsubsampling * vsubsampling);
1254 
1255         width = hsubsampling * 8;
1256         height = vsubsampling * 8;
1257 
1258         ySamplesH = hsubsampling;
1259         ySamplesV = vsubsampling;
1260 
1261         yWidth = width / ySamplesH;
1262         yHeight = height / ySamplesV;
1263     }
1264 
1265     void createCbBlocks(uint hsubsampling, uint vsubsampling)
1266     {
1267         cbBlocks = New!(Block[])(hsubsampling * vsubsampling);
1268 
1269         cbSamplesH = hsubsampling;
1270         cbSamplesV = vsubsampling;
1271 
1272         cbWidth = width / cbSamplesH;
1273         cbHeight = height / cbSamplesV;
1274     }
1275 
1276     void createCrBlocks(uint hsubsampling, uint vsubsampling)
1277     {
1278         crBlocks = New!(Block[])(hsubsampling * vsubsampling);
1279 
1280         crSamplesH = hsubsampling;
1281         crSamplesV = vsubsampling;
1282 
1283         crWidth = width / crSamplesH;
1284         crHeight = height / crSamplesV;
1285     }
1286 
1287     void free()
1288     {
1289         if (yBlocks.length) Delete(yBlocks);
1290         if (cbBlocks.length) Delete(cbBlocks);
1291         if (crBlocks.length) Delete(crBlocks);
1292     }
1293 
1294     Color4f getPixel(uint x, uint y) // coordinates relative to upper-left MCU corner
1295     {
1296         // Y block coordinates
1297         uint ybx = x / yWidth;
1298         uint yby = y / yHeight;
1299         uint ybi = yby * ySamplesH + ybx;
1300 
1301         // Pixel coordinates in Y block
1302         uint ybpx = x - ybx * yWidth;
1303         uint ybpy = y - yby * yHeight;
1304 
1305         // Cb block coordinates
1306         uint cbx = x / cbWidth;
1307         uint cby = y / cbHeight;
1308         uint cbi = cby * cbSamplesH + cbx;
1309 
1310         // Pixel coordinates in Cb block
1311         uint cbpx = (x - cbx * cbWidth)  / ySamplesH;
1312         uint cbpy = (y - cby * cbHeight) / ySamplesV;
1313 
1314         // Cr block coordinates
1315         uint crx = x / crWidth;
1316         uint cry = y / crHeight;
1317         uint cri = cry * crSamplesH + crx;
1318 
1319         // Pixel coordinates in Cr block
1320         uint crpx = (x - crx * crWidth)  / ySamplesH;
1321         uint crpy = (y - cry * crHeight) / ySamplesV;
1322 
1323         // Get color components
1324         float Y  = cast(float)yBlocks [ybi][ybpy * 8 + ybpx] + 128.0f;
1325         float Cb = cast(float)cbBlocks[cbi][cbpy * 8 + cbpx];
1326         float Cr = cast(float)crBlocks[cri][crpy * 8 + crpx];
1327 
1328         // Convert from YCbCr to RGB
1329         Color4f col;
1330         col.r = Y + 1.402f * Cr;
1331         col.g = Y - 0.34414f * Cb - 0.71414f * Cr;
1332         col.b = Y + 1.772f * Cb;
1333         col = col / 255.0f;
1334         col.a = 1.0f;
1335 
1336         return col;
1337     }
1338 }
1339 /*
1340  * Inverse discrete cosine transform (DCT) for 64x64 blocks
1341  *
1342  * The input coefficients should already have been multiplied by the
1343  * appropriate quantization table. We use fixed-point computation, with the
1344  * number of bits for the fractional component varying over the intermediate
1345  * stages.
1346  *
1347  * For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
1348  * discrete W transform and for the discrete Fourier transform", IEEE Trans. on
1349  * ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
1350  */
1351 void idct64(int* src)
1352 {
1353     enum blockSize = 64; // A DCT block is 8x8.
1354 
1355     enum w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16)
1356     enum w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16)
1357     enum w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16)
1358     enum w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16)
1359     enum w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16)
1360     enum w7 = 565; // 2048*sqrt(2)*cos(7*pi/16)
1361 
1362     enum w1pw7 = w1 + w7;
1363     enum w1mw7 = w1 - w7;
1364     enum w2pw6 = w2 + w6;
1365     enum w2mw6 = w2 - w6;
1366     enum w3pw5 = w3 + w5;
1367     enum w3mw5 = w3 - w5;
1368 
1369     enum r2 = 181; // 256/sqrt(2)
1370 
1371     // Horizontal 1-D IDCT.
1372     for (uint y = 0; y < 8; y++)
1373     {
1374         int y8 = y * 8;
1375         // If all the AC components are zero, then the IDCT is trivial.
1376         if (src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
1377             src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0)
1378         {
1379             int dc = src[y8+0] << 3;
1380             src[y8+0] = dc;
1381             src[y8+1] = dc;
1382             src[y8+2] = dc;
1383             src[y8+3] = dc;
1384             src[y8+4] = dc;
1385             src[y8+5] = dc;
1386             src[y8+6] = dc;
1387             src[y8+7] = dc;
1388             continue;
1389         }
1390 
1391         // Prescale.
1392         int x0 = (src[y8+0] << 11) + 128;
1393         int x1 = src[y8+4] << 11;
1394         int x2 = src[y8+6];
1395         int x3 = src[y8+2];
1396         int x4 = src[y8+1];
1397         int x5 = src[y8+7];
1398         int x6 = src[y8+5];
1399         int x7 = src[y8+3];
1400 
1401         // Stage 1.
1402         int x8 = w7 * (x4 + x5);
1403         x4 = x8 + w1mw7*x4;
1404         x5 = x8 - w1pw7*x5;
1405         x8 = w3 * (x6 + x7);
1406         x6 = x8 - w3mw5*x6;
1407         x7 = x8 - w3pw5*x7;
1408 
1409         // Stage 2.
1410         x8 = x0 + x1;
1411         x0 -= x1;
1412         x1 = w6 * (x3 + x2);
1413         x2 = x1 - w2pw6*x2;
1414         x3 = x1 + w2mw6*x3;
1415         x1 = x4 + x6;
1416         x4 -= x6;
1417         x6 = x5 + x7;
1418         x5 -= x7;
1419 
1420         // Stage 3.
1421         x7 = x8 + x3;
1422         x8 -= x3;
1423         x3 = x0 + x2;
1424         x0 -= x2;
1425         x2 = (r2*(x4+x5) + 128) >> 8;
1426         x4 = (r2*(x4-x5) + 128) >> 8;
1427 
1428         // Stage 4.
1429         src[y8+0] = (x7 + x1) >> 8;
1430         src[y8+1] = (x3 + x2) >> 8;
1431         src[y8+2] = (x0 + x4) >> 8;
1432         src[y8+3] = (x8 + x6) >> 8;
1433         src[y8+4] = (x8 - x6) >> 8;
1434         src[y8+5] = (x0 - x4) >> 8;
1435         src[y8+6] = (x3 - x2) >> 8;
1436         src[y8+7] = (x7 - x1) >> 8;
1437     }
1438 
1439     // Vertical 1-D IDCT.
1440     for (uint x = 0; x < 8; x++)
1441     {
1442         // Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial.
1443         // However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so
1444         // we do not bother to check for the all-zero case.
1445 
1446         // Prescale.
1447         int y0 = (src[8*0+x] << 8) + 8192;
1448         int y1 = src[8*4+x] << 8;
1449         int y2 = src[8*6+x];
1450         int y3 = src[8*2+x];
1451         int y4 = src[8*1+x];
1452         int y5 = src[8*7+x];
1453         int y6 = src[8*5+x];
1454         int y7 = src[8*3+x];
1455 
1456         // Stage 1.
1457         int y8 = w7*(y4+y5) + 4;
1458         y4 = (y8 + w1mw7*y4) >> 3;
1459         y5 = (y8 - w1pw7*y5) >> 3;
1460         y8 = w3*(y6+y7) + 4;
1461         y6 = (y8 - w3mw5*y6) >> 3;
1462         y7 = (y8 - w3pw5*y7) >> 3;
1463 
1464         // Stage 2.
1465         y8 = y0 + y1;
1466         y0 -= y1;
1467         y1 = w6*(y3+y2) + 4;
1468         y2 = (y1 - w2pw6*y2) >> 3;
1469         y3 = (y1 + w2mw6*y3) >> 3;
1470         y1 = y4 + y6;
1471         y4 -= y6;
1472         y6 = y5 + y7;
1473         y5 -= y7;
1474 
1475         // Stage 3.
1476         y7 = y8 + y3;
1477         y8 -= y3;
1478         y3 = y0 + y2;
1479         y0 -= y2;
1480         y2 = (r2*(y4+y5) + 128) >> 8;
1481         y4 = (r2*(y4-y5) + 128) >> 8;
1482 
1483         // Stage 4.
1484         src[8*0+x] = (y7 + y1) >> 14;
1485         src[8*1+x] = (y3 + y2) >> 14;
1486         src[8*2+x] = (y0 + y4) >> 14;
1487         src[8*3+x] = (y8 + y6) >> 14;
1488         src[8*4+x] = (y8 - y6) >> 14;
1489         src[8*5+x] = (y0 - y4) >> 14;
1490         src[8*6+x] = (y3 - y2) >> 14;
1491         src[8*7+x] = (y7 - y1) >> 14;
1492     }
1493 }