1 /*****************************************************************************/
2 // Copyright 2008-2019 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE: Adobe permits you to use, modify, and distribute this file in
6 // accordance with the terms of the Adobe license agreement accompanying it.
7 /*****************************************************************************/
8
9 #include "dng_opcode_list.h"
10
11 #include "dng_globals.h"
12 #include "dng_host.h"
13 #include "dng_memory_stream.h"
14 #include "dng_negative.h"
15 #include "dng_tag_values.h"
16 #include "dng_utils.h"
17
18 #include <algorithm>
19
20 /*****************************************************************************/
21
dng_opcode_list(uint32 stage)22 dng_opcode_list::dng_opcode_list (uint32 stage)
23
24 : fList ()
25 , fAlwaysApply (false)
26 , fStage (stage)
27
28 {
29
30 }
31
32 /******************************************************************************/
33
~dng_opcode_list()34 dng_opcode_list::~dng_opcode_list ()
35 {
36
37 Clear ();
38
39 }
40
41 /******************************************************************************/
42
Clear()43 void dng_opcode_list::Clear ()
44 {
45
46 for (size_t index = 0; index < fList.size (); index++)
47 {
48
49 if (fList [index])
50 {
51
52 delete fList [index];
53
54 fList [index] = NULL;
55
56 }
57
58 }
59
60 fList.clear ();
61
62 fAlwaysApply = false;
63
64 }
65
66 /******************************************************************************/
67
Swap(dng_opcode_list & otherList)68 void dng_opcode_list::Swap (dng_opcode_list &otherList)
69 {
70
71 fList.swap (otherList.fList);
72
73 std::swap (fAlwaysApply, otherList.fAlwaysApply);
74
75 std::swap (fStage, otherList.fStage);
76
77 }
78
79 /******************************************************************************/
80
MinVersion(bool includeOptional) const81 uint32 dng_opcode_list::MinVersion (bool includeOptional) const
82 {
83
84 uint32 result = dngVersion_None;
85
86 for (size_t index = 0; index < fList.size (); index++)
87 {
88
89 if (includeOptional || !fList [index]->Optional ())
90 {
91
92 result = Max_uint32 (result, fList [index]->MinVersion ());
93
94 }
95
96 }
97
98 return result;
99
100 }
101
102 /*****************************************************************************/
103
Apply(dng_host & host,dng_negative & negative,AutoPtr<dng_image> & image)104 void dng_opcode_list::Apply (dng_host &host,
105 dng_negative &negative,
106 AutoPtr<dng_image> &image)
107 {
108
109 DNG_REQUIRE (image.Get (), "Bad image in dng_opcode_list::Apply");
110
111 for (uint32 index = 0; index < Count (); index++)
112 {
113
114 dng_opcode &opcode (Entry (index));
115
116 if (opcode.AboutToApply (host,
117 negative,
118 image->Bounds (),
119 image->Planes ()))
120 {
121
122 opcode.Apply (host,
123 negative,
124 image);
125
126 }
127
128 }
129
130 }
131
132 /*****************************************************************************/
133
Append(AutoPtr<dng_opcode> & opcode)134 void dng_opcode_list::Append (AutoPtr<dng_opcode> &opcode)
135 {
136
137 if (opcode->OpcodeID () == dngOpcode_Private)
138 {
139 SetAlwaysApply ();
140 }
141
142 opcode->SetStage (fStage);
143
144 fList.push_back (NULL);
145
146 fList [fList.size () - 1] = opcode.Release ();
147
148 }
149
150 /*****************************************************************************/
151
Spool(dng_host & host) const152 dng_memory_block * dng_opcode_list::Spool (dng_host &host) const
153 {
154
155 if (IsEmpty ())
156 {
157 return NULL;
158 }
159
160 if (AlwaysApply ())
161 {
162 ThrowProgramError ();
163 }
164
165 dng_memory_stream stream (host.Allocator ());
166
167 stream.SetBigEndian ();
168
169 stream.Put_uint32 ((uint32) fList.size ());
170
171 for (size_t index = 0; index < fList.size (); index++)
172 {
173
174 stream.Put_uint32 (fList [index]->OpcodeID ());
175 stream.Put_uint32 (fList [index]->MinVersion ());
176 stream.Put_uint32 (fList [index]->Flags ());
177
178 fList [index]->PutData (stream);
179
180 }
181
182 return stream.AsMemoryBlock (host.Allocator ());
183
184 }
185
186 /*****************************************************************************/
187
FingerprintToStream(dng_stream & stream) const188 void dng_opcode_list::FingerprintToStream (dng_stream &stream) const
189 {
190
191 if (IsEmpty ())
192 {
193 return;
194 }
195
196 stream.Put_uint32 ((uint32) fList.size ());
197
198 for (size_t index = 0; index < fList.size (); index++)
199 {
200
201 stream.Put_uint32 (fList [index]->OpcodeID ());
202 stream.Put_uint32 (fList [index]->MinVersion ());
203 stream.Put_uint32 (fList [index]->Flags ());
204
205 if (fList [index]->OpcodeID () != dngOpcode_Private)
206 {
207
208 fList [index]->PutData (stream);
209
210 }
211
212 }
213
214 }
215
216 /*****************************************************************************/
217
Parse(dng_host & host,dng_stream & stream,uint32 byteCount,uint64 streamOffset)218 void dng_opcode_list::Parse (dng_host &host,
219 dng_stream &stream,
220 uint32 byteCount,
221 uint64 streamOffset)
222 {
223
224 Clear ();
225
226 TempBigEndian tempBigEndian (stream);
227
228 stream.SetReadPosition (streamOffset);
229
230 uint32 count = stream.Get_uint32 ();
231
232 #if qDNGValidate
233
234 if (gVerbose)
235 {
236
237 if (count == 1)
238 {
239 printf ("1 opcode\n");
240 }
241
242 else
243 {
244 printf ("%u opcodes\n", (unsigned) count);
245 }
246
247 }
248
249 #endif
250
251 for (uint32 index = 0; index < count; index++)
252 {
253
254 uint32 opcodeID = stream.Get_uint32 ();
255
256 AutoPtr<dng_opcode> opcode (host.Make_dng_opcode (opcodeID,
257 stream));
258
259 Append (opcode);
260
261 }
262
263 if (stream.Position () != streamOffset + byteCount)
264 {
265
266 ThrowBadFormat ("Error parsing opcode list");
267
268 }
269
270 }
271
272 /*****************************************************************************/
273