1 //
2 // (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
3 //
4 
5 #include "jpegmarkersegment.h"
6 #include "jpegmarkercode.h"
7 #include "util.h"
8 #include <vector>
9 #include <cstdint>
10 
11 using namespace std;
12 using namespace charls;
13 
CreateStartOfFrameSegment(int width,int height,int bitsPerSample,int componentCount)14 unique_ptr<JpegMarkerSegment> JpegMarkerSegment::CreateStartOfFrameSegment(int width, int height, int bitsPerSample, int componentCount)
15 {
16     ASSERT(width >= 0 && width <= UINT16_MAX);
17     ASSERT(height >= 0 && height <= UINT16_MAX);
18     ASSERT(bitsPerSample > 0 && bitsPerSample <= UINT8_MAX);
19     ASSERT(componentCount > 0 && componentCount <= (UINT8_MAX - 1));
20 
21     // Create a Frame Header as defined in T.87, C.2.2 and T.81, B.2.2
22     vector<uint8_t> content;
23     content.push_back(static_cast<uint8_t>(bitsPerSample)); // P = Sample precision
24     push_back(content, static_cast<uint16_t>(height));      // Y = Number of lines
25     push_back(content, static_cast<uint16_t>(width));       // X = Number of samples per line
26 
27     // Components
28     content.push_back(static_cast<uint8_t>(componentCount)); // Nf = Number of image components in frame
29     for (auto component = 0; component < componentCount; ++component)
30     {
31         // Component Specification parameters
32         content.push_back(static_cast<uint8_t>(component + 1)); // Ci = Component identifier
33         content.push_back(0x11);                                // Hi + Vi = Horizontal sampling factor + Vertical sampling factor
34         content.push_back(0);                                   // Tqi = Quantization table destination selector (reserved for JPEG-LS, should be set to 0)
35     }
36 
37     return make_unique<JpegMarkerSegment>(JpegMarkerCode::StartOfFrameJpegLS, move(content));
38 }
39 
40 
CreateJpegFileInterchangeFormatSegment(const JfifParameters & params)41 unique_ptr<JpegMarkerSegment> JpegMarkerSegment::CreateJpegFileInterchangeFormatSegment(const JfifParameters& params)
42 {
43     ASSERT(params.units == 0 || params.units == 1 || params.units == 2);
44     ASSERT(params.Xdensity > 0);
45     ASSERT(params.Ydensity > 0);
46     ASSERT(params.Xthumbnail >= 0 && params.Xthumbnail < 256);
47     ASSERT(params.Ythumbnail >= 0 && params.Ythumbnail < 256);
48 
49     // Create a JPEG APP0 segment in the JPEG File Interchange Format (JFIF), v1.02
50     vector<uint8_t> content { 'J', 'F', 'I', 'F', '\0' };
51     push_back(content, static_cast<uint16_t>(params.version));
52     content.push_back(static_cast<uint8_t>(params.units));
53     push_back(content, static_cast<uint16_t>(params.Xdensity));
54     push_back(content, static_cast<uint16_t>(params.Ydensity));
55 
56     // thumbnail
57     content.push_back(static_cast<uint8_t>(params.Xthumbnail));
58     content.push_back(static_cast<uint8_t>(params.Ythumbnail));
59     if (params.Xthumbnail > 0)
60     {
61         if (params.thumbnail)
62             throw CreateSystemError(ApiResult::InvalidJlsParameters, "params.Xthumbnail is > 0 but params.thumbnail == null_ptr");
63 
64         content.insert(content.end(), static_cast<uint8_t*>(params.thumbnail),
65             static_cast<uint8_t*>(params.thumbnail) + 3 * params.Xthumbnail * params.Ythumbnail);
66     }
67 
68     return make_unique<JpegMarkerSegment>(JpegMarkerCode::ApplicationData0, move(content));
69 }
70 
71 
CreateJpegLSExtendedParametersSegment(const JlsCustomParameters & params)72 unique_ptr<JpegMarkerSegment> JpegMarkerSegment::CreateJpegLSExtendedParametersSegment(const JlsCustomParameters& params)
73 {
74     vector<uint8_t> content;
75 
76     // Parameter ID. 0x01 = JPEG-LS preset coding parameters.
77     content.push_back(1);
78 
79     push_back(content, static_cast<uint16_t>(params.MAXVAL));
80     push_back(content, static_cast<uint16_t>(params.T1));
81     push_back(content, static_cast<uint16_t>(params.T2));
82     push_back(content, static_cast<uint16_t>(params.T3));
83     push_back(content, static_cast<uint16_t>(params.RESET));
84 
85     return make_unique<JpegMarkerSegment>(JpegMarkerCode::JpegLSExtendedParameters, move(content));
86 }
87 
88 
CreateColorTransformSegment(ColorTransformation transformation)89 unique_ptr<JpegMarkerSegment> JpegMarkerSegment::CreateColorTransformSegment(ColorTransformation transformation)
90 {
91     return make_unique<JpegMarkerSegment>(
92         JpegMarkerCode::ApplicationData8,
93         vector<uint8_t> { 'm', 'r', 'f', 'x', static_cast<uint8_t>(transformation) });
94 }
95 
96 
CreateStartOfScanSegment(int componentIndex,int componentCount,int allowedLossyError,InterleaveMode interleaveMode)97 unique_ptr<JpegMarkerSegment> JpegMarkerSegment::CreateStartOfScanSegment(int componentIndex, int componentCount, int allowedLossyError, InterleaveMode interleaveMode)
98 {
99     ASSERT(componentIndex >= 0);
100     ASSERT(componentCount > 0);
101 
102     // Create a Scan Header as defined in T.87, C.2.3 and T.81, B.2.3
103     vector<uint8_t> content;
104 
105     content.push_back(static_cast<uint8_t>(componentCount));
106     for (auto i = 0; i < componentCount; ++i)
107     {
108         content.push_back(static_cast<uint8_t>(componentIndex + i));
109         content.push_back(0);  // Mapping table selector (0 = no table)
110     }
111 
112     content.push_back(static_cast<uint8_t>(allowedLossyError)); // NEAR parameter
113     content.push_back(static_cast<uint8_t>(interleaveMode)); // ILV parameter
114     content.push_back(0); // transformation
115 
116     return make_unique<JpegMarkerSegment>(JpegMarkerCode::StartOfScan, move(content));
117 }
118