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