-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecoder.c
executable file
·1915 lines (1598 loc) · 57.8 KB
/
decoder.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
mmmm mmmmmm mmm mmmm mmmm mmmmmm mmmmm
# "m # m" " m" "m # "m # # "#
# # #mmmmm # # # # # #mmmmm #mmmm"
# # # # # # # # # # "m
#mmm" #mmmmm "mmm" #mm# #mmm" #mmmmm # "
*/
/* DEFINES */
#define DEBUG
#ifdef DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
#define M_PI 3.14159265358979323846
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_RESET "\x1b[0m"
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef float f32;
typedef double f64;
typedef unsigned char byte;
typedef enum { false, true } bool;
/* END DEFINES */
#define null "null"
/* color models */
#define RGB "RGB"
#define CMYK "CMYK"
#define Gray "Gray"
/* color spaces */
#define sRGB "sRGB"
typedef struct {
u64 size; /* in bytes */
char *path; /* Absolute path */
u64 width;
u64 height;
char *color_space;
char *color_model;
u64 bits_per_sample;
byte *data; /* decoded data width*height sized array */
} JPEG;
/*
If a 0xFF byte occurs in the compressed image data either a zero byte (0x00) or a
marker identifier follows it. Not only marker that should be found once the image
data is started is an EOI. When a 0xFF byte is found followed 1 byte (0x00) the
zero byte must be discarded.
*/
#define nul 0x00 /* JPEG reserved */
#define TEM 0x01 /* Temporary marker, arithmetic coding */
#define RESn 0x02 /* Reserved 0x02 - 0xBF */
#define SOF0 0xC0 /* Start Of Frame 0, baseline jpeg */
#define SOF1 0xC1 /* Start Of Frame 1, extended sequential, huffman */
#define SOF2 0xC2 /* Start Of Frame 2, progressive, huffman */
#define SOF3 0xC3 /* Start Of Frame 3, lossless, huffman */
#define DHT 0xC4 /* Define Huffman Table */
#define SOF5 0xC5 /* Start Of Frame 5, differential sequential, huffman */
#define SOF6 0xC6 /* Start Of Frame 6, differential progressive, huffman */
#define SOF7 0xC7 /* Start Of Frame 7, differential lossless, huffman */
#define JPG 0xC8 /* JPEG Extensions */
#define SOF9 0xC9 /* Start Of Frame 9, extended sequential, arithmetic */
#define SOF10 0xCA /* Start Of Frame 10, progressive, arithmetic */
#define SOF11 0xCB /* Start Of Frame 11, lossless, arithmetic */
#define DAC 0xCC /* Define Arithmetic Coding */
#define SOF13 0xCD /* Start Of Frame 13, differential sequential, arithmetic */
#define SOF14 0xCE /* Start Of Frame 14, differential progressive, arithmetic */
#define SOF15 0xCF /* Start Of Frame 15, differential lossless, arithmetic */
#define RST0 0xD0 /* Restart Marker 0 */
#define RST1 0xD1 /* Restart Marker 1 */
#define RST2 0xD2 /* Restart Marker 2 */
#define RST3 0xD3 /* Restart Marker 3 */
#define RST4 0xD4 /* Restart Marker 4 */
#define RST5 0xD5 /* Restart Marker 5 */
#define RST6 0xD6 /* Restart Marker 6 */
#define RST7 0xD7 /* Restart Marker 7 */
#define SOI 0xD8 /* Start Of image */
#define EOI 0xD9 /* End Of Image */
#define SOS 0xDA /* Start Of Scan */
#define DQT 0xDB /* Define Quantizaion Table */
#define DNL 0xDC /* Define Number of Lines */
#define DRI 0xDD /* Define Restart Interval */
#define DHP 0xDE /* Define Hierarchical Progression */
#define EXP 0xDF /* Expand Reference Component */
#define APP0 0xE0 /* Application Segment 0, JFIF, JFXX, CIFF, Ocad, AVI1 */
#define APP1 0xE1 /* Application Segment 1, EXIF, ExtendedXMP, QVCI, FLIR, RawThermalImage, XMP, Adobe XMP */
#define APP2 0xE2 /* Application Segment 2, ICC color profile, FPXR, MPF, PreviewImage */
#define APP3 0xE3 /* Application Segment 3, JPS, Meta, Stim, ThermalData, PreviewImage */
#define APP4 0xE4 /* Application Segment 4, Scalado, FPXR, ThermalParams, PreviewImage */
#define APP5 0xE5 /* Application Segment 5, RMETA, SamsungUniqueID, ThermalCalibration, PreviewImage */
#define APP6 0xE6 /* Application Segment 6, EPPIM, NITF, HP_TDHD, GoPro, DJI_DTAT */
#define APP7 0xE7 /* Application Segment 7, Pentax, Huawei, Qualcomm */
#define APP8 0xE8 /* Application Segment 8, SPIFF */
#define APP9 0xE9 /* Application Segment 9, MediaJukebox */
#define APP10 0xEA /* Application Segment 10, ActiveObject, PhotoStudio */
#define APP11 0xEB /* Application Segment 11, JPEG-HDR, JUMBF */
#define APP12 0xEC /* Application Segment 12, Picture Info (older digicams), Photoshop Save for Web: Ducky */
#define APP13 0xED /* Application Segment 13, Photoshop Save As: IRB, 8BIM, IPTC */
#define APP14 0xEE /* Application Segment 14, Adobe */
#define APP15 0xEF /* Application Segment 15, GraphicConverter */
#define JPG0 0xF0 /* JPEG Extension 0 */
#define JPG1 0xF1 /* JPEG Extension 1 */
#define JPG2 0xF2 /* JPEG Extension 2 */
#define JPG3 0xF3 /* JPEG Extension 3 */
#define JPG4 0xF4 /* JPEG Extension 4 */
#define JPG5 0xF5 /* JPEG Extension 5 */
#define JPG6 0xF6 /* JPEG Extension 6 */
#define JPG7 0xF7 /* JPEG Extension 7 */
#define JPG8 0xF8 /* JPEG Extension 8 */
#define JPG9 0xF9 /* JPEG Extension 9 */
#define JPG10 0xFA /* JPEG Extension 10 */
#define JPG11 0xFB /* JPEG Extension 11 */
#define JPG12 0xFC /* JPEG Extension 12 */
#define JPG13 0xFD /* JPEG Extension 13 */
#define COM 0xFE /* Comment */
#define marker 0xFF /* Segment */
/* Exif IFD tags */
#define EXIF_WIDTH 256
#define EXIF_HEIGHT 257
#define EXIF_BPS 258
#define EXIF_COLOR_SPACE 40961
#define EXIF_PIXELXD 40962
#define EXIF_PIXELYD 40963
#define EXIF_ZOOM_RATIO 41988
/* Interoperability IFD tags */
#define exifPointer 34665
#define interPointer 40965
#define gpsPointer 34853
/* ICC profile tags */
#define ICC_RGB 0x52474220
#define ICC_CMYK 0x434D594B
#define ICC_GRAY 0x47524159
/*
SOF0 (Start Of Frame 0) marker:
+----------------------+---------+---------------------------------------------------+
| Field | Size | Description |
+----------------------+---------+---------------------------------------------------+
| Marker Identifier | 2 bytes | 0xFF, 0xC0 to identify SOF0 marker |
| Length | 2 bytes | This value equals to 8 + components*3 value |
| Data precision | 1 byte | This is in bits/sample, usually 8 |
| Image height | 2 bytes | This must be > 0 |
| Image width | 2 bytes | This must be > 0 |
| Number of components | 1 byte | 1 = grey scaled, 3 = color YCbCr or YIQ, |
| | | 4 = color CMYK |
| Each component | 3 bytes | Read each component data of 3 bytes. It contains, |
| | | (component Id (1 byte) (1 = Y, 2 = Cb, 3 = Cr, |
| | | 4 = I, 5 = Q), sampling factors (1 byte) |
| | | (bit 0-3 vertical, 4-7 horizontal), |
| | | quantization table number (1 byte))) |
+----------------------+---------+---------------------------------------------------+
APP0 (JFIF segment marker) marker:
-----------------------------------------------------------------------------------
| Field | Size | Description |
-----------------------------------------------------------------------------------
| Marker Identifier | 2 bytes | 0xFF, 0xE0 to identify APP0 marker |
| Length | 2 bytes | It must be >= 16 |
| File Identifier Mark | 5 bytes | This identifies JFIF |
| Major revision number | 1 byte | Should be 1, otherwise error |
| Minor revision number | 1 byte | Should be 0..2, otherwise try |
| Units for x/y densities | 1 byte | 0 = no units, x/y - density specify ratio |
| | | instead 1 = x/y - density are dots/inch |
| | | 2 = x/y - density are dots/cm |
| X-density | 2 bytes | It should be <> 0 |
| Y-density | 2 bytes | It should be <> 0 |
| Thumbnail width | 1 byte | |
| Thumbnail height | 1 byte | |
| Bytes to be read | n bytes | For thumbnail (RGB 24 bit), |
| | | n = width*height*3 |
-----------------------------------------------------------------------------------
Remarks:
- If there's no 'JFIF', or the length is < 16, the it is probably not a JFIF
segment and should be ingored
- Normally units=0, x-dens=1, y-dens=1, meaning that the aspect ratio is 1:1
(evenly scaled)
- JFIF files including thumbnails are very rare, the thumbnail can usually
be ignored. If there's no, then width=0 and height=0. If the length doesn't
match the thumbnail size, there is warning.
DHT (Define Huffman Table) marker:
--------------------------------------------------------------------------------------
| Field | Size | Description |
--------------------------------------------------------------------------------------
| Marker Identifier | 2 bytes | 0xFF, 0xC4 to identify DHT marker |
| Length | 2 bytes | This specify length of Huffman table |
| HT information | 1 byte | bit 0..3: number of HT |
| | | bit 4: type of HT, 0=DC table, 1=AC table |
| | | bit 5..7: not used, must be 0 |
| Number of Symbols | 16 bytes | Number of symbols with codes of length 1..16, |
| | | the sum(n) of these bytes is the total number |
| | | of codes, which must be <= 256 |
| Symbols | n bytes | Table containing the symbols in order of |
| | | increasing code length (n=total number of codes) |
--------------------------------------------------------------------------------------
Remarks:
A single DHT segment may contain multiple HTs, each with its own information byte.
DRI (Define Restart Interval) marker:
------------------------------------------------------------------------------------
| Field | Size | Description |
------------------------------------------------------------------------------------
| Marker Identifier | 2 bytes | 0xFF, 0xDD identifies DRI marker |
| Length | 2 bytes | It must be 4 |
| Restart interval | 2 bytes | This is units of MCU blocks, means that every |
| | | n MCU blocks a RSTn marker can be found. The |
| | | first marker will be RST0, then RST1 etc, after |
| | | RST7 repeating from RST0 |
------------------------------------------------------------------------------------
DQT (Define Quantization Table) marker:
-------------------------------------------------------------------------------------
| Field | Size | Description |
-------------------------------------------------------------------------------------
| Marker Identifier | 2 bytes | 0xFF, 0xDB identifies DQT |
| Length | 2 bytes | This gives the length of QT |
| QT information | 1 byte | bit 0..3: number of QT |
| | | bit 4..7: precision of QT, 0=8 bit, otherwise 16 |
| Bytes | n bytes | This gives QT values, n = 64*(precision+1) |
-------------------------------------------------------------------------------------
SOS (Start Of Scan) marker:
-------------------------------------------------------------------------------------
| Field | Size | Description |
-------------------------------------------------------------------------------------
| Marker Identifier | 2 bytes | 0xFF, 0xDA identify SOS marker |
| Length | 2 bytes | This must be equal to 6+2*(number of components) |
| Number of components | 1 byte | This must be >= 1 and <= 4, usually 1 or 3 |
| Each component | 2 bytes | For each component, read 2 bytes. It contains, |
| | 1 byte | Component Id (1=Y, 2=Cb, 3=Cr, 4=I, 5=Q) |
| | 1 byte | Huffman table to use: bit 0..3: AC table |
| | | bit 4..7: DC table |
| Ignorable Bytes | 3 bytes | We have to skip 3 bytes |
-------------------------------------------------------------------------------------
Remarks:
The image data (scans) is immediately following the SOS segment.
APP1 (EXIF segment marker) marker:
+-------------------------------------------------------------------------------
| Field | Size | Description |
+------------------------------------------------------------------------------+
| Marker Identifier | 2 bytes | 0xFF, 0xE1 to identify APP1 marker |
| Length | 2 bytes | |
| File Identifier Mark | 6 bytes | This identifies EXIF |
| TIFF Header | 8 bytes | |
| 0th IFD | var | |
| Exif IFD | var | |
| Interoperability IFD | var | |
| GPS IFD | var | |
| 1st IFD | var | |
+--------------------------------------------------------------------------------
TIFF Header:
------------------------------------------------------------------------------------------------
| Field | Size | Description |
------------------------------------------------------------------------------------------------
| Byte order | 2 bytes | 0x49 0x49 - little endian, 0x4D, 0x4D - big endian |
| TIFF ID | 2 bytes | Always 0x00, 0x2A |
| Offset to 0th IFD | 4 bytes | From start of the TIFF header |
------------------------------------------------------------------------------------------------
0th IFD:
+-------------------------+------------------+---------------------------------------+
| Field | Size | Description |
+-------------------------+------------------+---------------------------------------+
| Field Count | 2 bytes | |
| IFD Fields | count * 12 bytes | Contains Offsets to Exif and GPS IFDs |
| Offset to 0th IFD | 4 bytes | From start of the TIFF header |
| Field Data | var | Datra that does not fit in 4 bytes |
+-------------------------+------------------+---------------------------------------+
Exif IFD:
+-------------------------+------------------+-----------------------------------------+
| Field | Size | Description |
+-------------------------+------------------+-----------------------------------------+
| Field Count | 2 bytes | |
| IFD Fields | count * 12 bytes | Contains offset to Interoperability IFD |
| Offset to 1st IFD | 4 bytes | From start of the TIFF header |
| Field Data | var | Datra that does not fit in 4 bytes |
+-------------------------+------------------+-----------------------------------------+
Interoperability IFD:
+-------------------------+------------------+------------------------------------+
| Field | Size | Description |
+-------------------------+------------------+------------------------------------+
| Field Count | 2 bytes | |
| IFD Fields | count * 12 bytes | |
| Offset to 1st IFD | 4 bytes | From start of the TIFF header |
| Field Data | var | Datra that does not fit in 4 bytes |
+-------------------------+------------------+------------------------------------+
GPS IFD:
+-------------------------+------------------+------------------------------------+
| Field | Size | Description |
+-------------------------+------------------+------------------------------------+
| Field Count | 2 bytes | |
| IFD Fields | count * 12 bytes | |
| Offset to 1st IFD | 4 bytes | From start of the TIFF header |
| Field Data | var | Datra that does not fit in 4 bytes |
+-------------------------+------------------+------------------------------------+
1st IFD:
+-------------------------+------------------+----------------------------------------+
| Field | Size | Description |
+-------------------------+------------------+----------------------------------------+
| Field Count | 2 bytes | |
| IFD Fields | count * 12 bytes | Offset and size of thumbnail data |
| Offset to 1st IFD | 4 bytes | From start of the TIFF header |
| Field Data | var | Data that does not fit in 4 bytes |
| Thumbnail Image Data | var | |
+-------------------------+------------------+----------------------------------------+
IFD Field:
+-------------------------+---------+-----------------------------------------------------------+
| Field | Size | Description |
+-------------------------+---------+-----------------------------------------------------------+
| Tag ID | 2 bytes | Tag IDs are not unique across IFDs |
| Type ID | 2 bytes | 1 - Byte |
| | | 2 - ASCII (byte array) |
| | | 3 - Short (uint16) |
| | | 4 - Long (uint32) |
| | | 5 - Rational (2 * uint32) |
| | | 7 - Undefined (byte array) |
| | | 9 - SLong (int32) |
| | | 10 - SRational (2 * int32) |
| Count or Components | 4 bytes | Byte array - count, other - number of components |
| Value or Offset To Data | 4 bytes | If field data exceeds 4 bytes - offfset, otherwise - data |
+-------------------------+---------+-----------------------------------------------------------+
Remark:
All offsets from start of TIFF header
ICC Profile:
+-------------------------+-------------------+
| Field | Size |
+-------------------------+-------------------+
| Profile header | 128 bytes |
| Tag table | 4 + 12 * each tag |
| Tagged element data | var |
+-------------------------+-------------------+
ICC Profile header fields:
+----------------------------+----------+-------------------------------------------------+
| Field | Size | Description |
+----------------------------+----------+-------------------------------------------------+
| Profile size | 4 bytes | |
| CMM type | 4 bytes | Preferred CMM type |
| Profile version | 4 bytes | |
| Profile/Device class | 4 bytes | |
| Colour space of data | 4 bytes | Possibly a derived space |
| PCS | 4 bytes | |
| Data and time | 12 bytes | Then this profile was first created |
| 'acsp' | 4 bytes | Profile file signature |
| Primary platform signature | 4 bytes | |
| Profile flags | 4 bytes | To indicate various options for the CMM |
| Device manufacturer | 4 bytes | Of the device for which this profile is created |
| Device attributes | 8 bytes | Unique to the particular device setup |
| Rendering Intent | 4 bytes | |
| The nCIEXYZ values | 12 bytes | Of the illuminant of the PCS |
| Profile creator signature | 4 bytes | |
| Profile ID | 16 bytes | |
| Reserved | 28 bytes | For future expansion and shall be set to zero |
+----------------------------+----------+-------------------------------------------------+
Remark:
All fields following each other, all big endian encoded
Data colour space signatures:
+-------------------+--------------+
| Colour space type | Hex encoding |
+-------------------+--------------+
| nCIEXYZ or PCSXYZ | 58595A20 |
| CIELAB or PCSLAB | 4C616220 |
| CIELUV | 4C757620 |
| YCbCr | 59436272 |
| CIEYxy | 59787920 |
| RGB | 52474220 |
| Gray | 47524159 |
| HSV | 48535620 |
| HLS | 484C5320 |
| CMYK | 434D594B |
| CMY | 434D5920 |
| 2 colour | 32434C52 |
| 3 colour | 33434C52 |
| 4 colour | 34434C52 |
| 5 colour | 35434C52 |
| 6 colour | 36434C52 |
| 7 colour | 37434C52 |
| 8 colour | 38434C52 |
| 9 colour | 39434C52 |
| 10 colour | 41434C52 |
| 11 colour | 42434C52 |
| 12 colour | 43434C52 |
| 13 colour | 44434C52 |
| 14 colour | 45434C52 |
| 15 colour | 46434C52 |
+-------------------+--------------+
Colour encoding types:
nCIEXYZ -> CIELAB, PCSXYZ, PCSLAB, CIELUV, CIEYxy
GRAY
RGB -> HLS, HSV, YCbCr
CMY
CMYK
*/
void setij(int *indexi, int *indexj, int a, int m[8][8]) {
m[(*indexi)][(*indexj)] = a;
if ((*indexi) % 2 == 0) {
if ((*indexj) % 2 == 0) {
if ((*indexi) == 0 || (*indexi) == 7) (*indexj) += 1;
else {
(*indexi) -= 1;
(*indexj) += 1;
}
} else {
(*indexi) += 1;
(*indexj) -= 1;
}
} else {
if ((*indexj) % 2 == 0) {
if ((*indexi) == 7) (*indexj) += 1;
else if ((*indexj) == 0 || (*indexj) == 7) (*indexi) += 1;
else {
(*indexi) += 1;
(*indexj) -= 1;
}
} else {
if ((*indexj) == 7) (*indexi) += 1;
else {
(*indexi) -= 1;
(*indexj) += 1;
}
}
}
}
int base10to2LEN(int a) {
if (a == 0) return 1;
int res = 0;
while (a != 0) {
a /= 2;
res++;
}
return res;
}
void base10to2(char res[], int a, int l) {
int i = l-1;
for (int j = 0; j < l; j++) res[j] = '0';
while (a != 0) {
res[i] = (a % 2) + '0';
a /= 2;
i--;
}
}
int base2to10(char *s, int l, bool r) {
int res = 0;
if (r) {
int j = 0;
for (int i = l; i >= 0; i--) {
int a = s[i] - '0';
res += a * pow(2, j);
j++;
}
} else {
int j = l-1;
for (int i = 0; i < l; i++) {
int a = s[i] - '0';
res += a * pow(2, j);
j--;
}
}
return res;
}
char read_bit(byte data, int i) {
return ((data >> i) & 0x01) + '0';
}
void dec2hex(char res[2], int a) {
int t1 = a / 16;
int t2 = a % 16;
res[0] = t1 + '0';
res[1] = t2 + '0';
}
int read_bytes_le(const byte *data, int *i, int count) {
int res = data[*i];
int k = 8;
for (int j = 1; j < count; j++) {
res |= data[*i+j]<<k;
k += 8;
}
*i += count;
return res;
}
int read_bytes_be(const byte *data, int *i, int count) {
int res = data[*i+count-1];
int k = 8;
for (int j = count-2; j >= 0; j--) {
res |= data[*i+j]<<k;
k += 8;
}
*i += count;
return res;
}
int bin_to_int(char *bin, int l) {
int res = 0;
int j = 0;
for (int i = l-1; i >= 0; i--) {
int b = bin[j] - '0';
res += b * pow(2, i);
j++;
}
return res;
}
double alpha(int x) { return (x == 0) ? 1 / sqrt(2) : 1; }
void DCT(int m[8][8]) {
int t[8][8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
t[i][j] = m[i][j];
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
double sum = 0;
for (int u = 0; u < 8; u++)
for (int v = 0; v < 8; v++)
sum += alpha(u) * alpha(v) * t[u][v] * cos(((2*x + 1) * M_PI * u) / 16) * cos(((2*y + 1) * M_PI * v) / 16);
sum /= 4;
m[x][y] = sum;
}
}
}
int *YCbCr2RGB(int Y, int Cb, int Cr) {
float R = Cr * 1.402 + Y;
float B = Cb * 1.772 + Y;
float G = (Y - 0.114 * B - 0.299 * R) / 0.587;
R += 128;
G += 128;
B += 128;
R = fmin(fmax(0.0, (float)R), 255.0);
G = fmin(fmax(0.0, (float)G), 255.0);
B = fmin(fmax(0.0, (float)B), 255.0);
int *res = malloc(3 * sizeof(int));
res[0] = R;
res[1] = G;
res[2] = B;
return res;
}
int readDC(int datai, int dd, char image_data[]) {
char DC[dd];
for (int h = 0; h < dd; h++)
DC[h] = image_data[datai+h];
int value = base2to10(DC, dd, false);
if (DC[0] == '0') value = value - pow(2, dd) + 1;
return value;
}
int TIFFi = 0;
int scale = 0;
int exifOffset = -1;
int interOffset = -1;
int gpsOffset = -1;
int stOffset = -1;
int zoom = 0;
void IFDFields(byte *data, int *i, bool encoding, JPEG *jpeg) {
int len = (encoding == true) ? read_bytes_be(data, i, 2) : read_bytes_le(data, i, 2);
for (int j = 0; j < len; j++) {
int tagID = (encoding == true) ? read_bytes_be(data, i, 2) : read_bytes_le(data, i, 2);
int typeID = (encoding == true) ? read_bytes_be(data, i, 2) : read_bytes_le(data, i, 2);
int count = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
int size = 0;
switch (typeID) {
case 1:
size = count;
break;
case 2:
size = count;
break;
case 3:
size = 2 * count;
break;
case 4:
size = 4 * count;
break;
case 5:
size = 8 * count;
break;
case 7:
size = count;
break;
case 9:
size = 4 * count;
break;
case 10:
size = 8 * count;
break;
default:
break;
}
int offset = 0;
int t = 0;
if (size > 4) {
offset = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
*i -= (4 + 4 + 2 + 2 + j * 12 + 2 + 8);
*i += offset;
}
switch (typeID) {
case 1:
t = 4 - count;
for (int index = 0; index < count; index++) {
byte value = (encoding == true) ? read_bytes_be(data, i, 1) : read_bytes_le(data, i, 1);
}
break;
case 2:
t = 4 - count;
for (int index = 0; index < count; index++) {
byte value = (encoding == true) ? read_bytes_be(data, i, 1) : read_bytes_le(data, i, 1);
/* May be broken if tagIDs are not unique between IFDs */
}
break;
case 3:
t = 4 - count * 2;
u32 color_space;
for (int index = 0; index < count; index++) {
u16 value = (encoding == true) ? read_bytes_be(data, i, 2) : read_bytes_le(data, i, 2);
if (tagID == EXIF_PIXELXD && value != 0) { jpeg->width = value; }
if (tagID == EXIF_PIXELYD && value != 0) { jpeg->height = value; }
if (tagID == EXIF_WIDTH && value != 0) { jpeg->width = value; }
if (tagID == EXIF_HEIGHT && value != 0) { jpeg->height = value; }
if (tagID == EXIF_BPS) (*jpeg).bits_per_sample = value;
if (tagID == EXIF_COLOR_SPACE) {
if (value != 0) color_space = value;
}
}
if (color_space == 1) jpeg->color_space = sRGB;
if (color_space == 65535) jpeg->color_space = null;
break;
case 4:
t = 4 - count * 4;
for (int index = 0; index < count; index++) {
u32 value = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
if (tagID == EXIF_PIXELXD && value != 0) { jpeg->width = value; }
if (tagID == EXIF_PIXELYD && value != 0) { jpeg->height = value; }
if (tagID == EXIF_WIDTH && value != 0) { jpeg->width = value; }
if (tagID == EXIF_HEIGHT && value != 0) { jpeg->height = value; }
if (tagID == exifPointer) exifOffset = value;
else if (tagID == gpsPointer) gpsOffset = value;
else if (tagID == interPointer) interOffset = value;
}
break;
case 5:
t = 4 - count * 8;
for (int index = 0; index < count; index++) {
u32 value1 = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
u32 value2 = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
if (tagID == EXIF_ZOOM_RATIO) {
zoom = value1;
}
}
break;
case 7:
t = 4 - count * 1;
for (int index = 0; index < count; index++) {
byte value = (encoding == true) ? read_bytes_be(data, i, 1) : read_bytes_le(data, i, 1);
}
break;
case 9:
t = 4 - count * 4;
for (int index = 0; index < count; index++) {
s32 value = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
debug("%d ", value);
}
break;
case 10:
t = 4 - count * 8;
for (int index = 0; index < count; index++) {
s32 value1 = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
s32 value2 = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
debug("%d %d", value1, value2);
}
break;
default:
break;
}
if (size > 4) {
*i -= (offset + size);
*i += (4 + 4 + 2 + 2 + j * 12 + 2 + 8);
} else {
*i += t;
}
}
stOffset = (encoding == true) ? read_bytes_be(data, i, 4) : read_bytes_le(data, i, 4);
}
int restart_interval = 0;
void read8x8(int a, int mn, int m[8][8], int DC_id, int AC_id, char image_data[], int *datai, int *huffmantable, char *huffcodes, int k, int index) {
for (int p = 0; p < 8; p++)
for (int q = 0; q < 8; q++)
m[p][q] = 0;
int indexi = 0;
int indexj = 1;
bool findDC = false;
if (restart_interval != 0 && a % restart_interval == 1 && mn == 1) {
while ((*datai) % 8 != 0) (*datai)++;
// exit(0);
}
int entered = 0;
while (*datai < (k-1)*8) {
bool e = false;
int f = 0;
int fcod = 0;
while (f < index) {
int n = huffmantable[f];
char tmp[2];
dec2hex(tmp, n);
int n_class = tmp[0] - '0';
int n_id = tmp[1] - '0';
int l = huffmantable[f+1];
char c[l];
for (int p = fcod; p < fcod + l; p++)
c[p-fcod] = huffcodes[p];
if (n_id != DC_id && n_id != AC_id) {f += 3; fcod += l; continue;}
if (findDC && n_class == 0) { f += 3; fcod += l; continue; }
if (!findDC && n_class != 0) { f += 3; fcod += l; continue; }
int t = *datai;
int r = 0;
while (r < l) {
if (c[r] == image_data[t]) {
t++;
r++;
} else break;
}
if (r != l) {f += 3; fcod += l; continue;}
char d[2];
dec2hex(d, huffmantable[f+2]);
int dd = huffmantable[f+2];
if (n_class == 0) {
/* DC */
findDC = true;
entered++;
*datai += l;
if (dd == 0) m[0][0] = 0;
else m[0][0] = readDC(*datai, dd, image_data);
*datai += dd;
} else {
/* AC */
entered++;
*datai += l;
if (dd == 0) {
e = true;
break;
}
int p1 = d[0] - '0';
int p2 = d[1] - '0';
char AC[p2];
/* p1 - count of zeros to write */
bool le = false;
for (int g = 0; g < p1; g++) {
if (indexi >= 8 || indexj >= 8) {e = true; le = true; break;}
setij(&indexi, &indexj, 0, m);
entered++;
}
if (le) break;
/* p2 - len of AC */
for (int g = 0; g < p2; g++)
AC[g] = image_data[*datai+g];
*datai += p2;
/* read AC */
int value = base2to10(AC, p2, false);
if (AC[0] == '0') value = value - pow(2, p2) + 1;
if (indexi >= 8 || indexj >= 8) {e = true; break;}
setij(&indexi, &indexj, value, m);
}
if (entered >= 64) { e = true; break; }
f += 3;
fcod += l;
}
if (e) break;
}
}
int HC_size(int size, int i, byte data[]) {
int res = 0;
for (int j = 0; j < size; j++)
for (int g = 0; g < data[1+i+j]; g++)
res += j + 1;
return res;
}
int HT_size(int size, int i, byte data[]) {
int res = 0;
for (int j = 0; j < size; j++)
for (int g = 0; g < data[1+i+j]; g++)
res++;
return res;
}
int QT_size(int precision) {
return precision*precision + 2;
}
void readDQT(byte data[], int *i, int offset, int *qtable, int precision, int qid) {
int table[precision][precision];
int p = 0;
int q = 0;
for (int t = 0; t < precision*precision; t++) {
int value = read_bytes_be(data, i, precision/8);
setij(&p, &q, value, table);
}
qtable[offset] = qid;
qtable[offset + 1] = precision*precision;
for (int p = 0; p < precision; p++)
for (int q = 0; q < precision; q++)
qtable[offset + 2 + p*precision + q] = table[p][q];
}
void readHT(int size, int *huffmantable, char *huffcodes, int *index, int *hindex, int *i, byte data[]) {
int num = data[(*i)];
(*i)++;
u8 counts[size];
for (int j = 0; j < size; j++) counts[j] = data[*i+j];
*i += size;
int code = 0;
for (int j = 0; j < size; j++) {
for (int g = 0; g < counts[j]; g++) {
// if ((*index) == 0) huffmantable = malloc(sizeof(int) * 3);
// else huffmantable = realloc(huffmantable, ((*t)+1)*(sizeof(int) * 3));
huffmantable[(*index)] = num;
huffmantable[(*index)+1] = j+1;
huffmantable[(*index)+2] = (int)data[*i];
int len = j + 1;
char c[len];
base10to2(c, code, len);
// if (*hindex == 0) huffcodes = (int*)malloc((*huff_size));
// else huffcodes = (int*)realloc(huffcodes, (*huff_size));
for (int k = 0; k < len; k++)
huffcodes[(*hindex)+k] = c[k];
*index += 3;
*hindex += len;
code++;
(*i)++;
}
// exit(0);
code <<= 1;
}
}
int headerI = -1;
JPEG processJPEG(char *path, char *outputPath) {
int *huffmantable;
int *qtable;
char *huffcodes;
int *qnums;
int hindex = 0;
int qtable_size = 0;
int index = 0;
int huff_size = 0;
int ind = 0;
int t = 0;
int SOF_number_of_components = 0;
/* Open file for reading bytes */
FILE *file = fopen(path, "rb");
/* Get size = count of bytes */
int err = fseek(file, 0L, SEEK_END);
if (err) {
exit(1);
}
long size = ftell(file);
rewind(file);
/* Output model */
JPEG jpeg;
jpeg.size = size;
jpeg.path = path;
jpeg.width = 0;
jpeg.height = 0;
jpeg.color_space = null;
jpeg.color_model = null;
jpeg.bits_per_sample = 0;
/* Read bytes */