33 |
33 |
#include "config.h"
|
34 |
34 |
|
35 |
35 |
#include "webpimage.hpp"
|
36 |
|
#include "image_int.hpp"
|
37 |
36 |
#include "futils.hpp"
|
38 |
37 |
#include "basicio.hpp"
|
39 |
38 |
#include "tags.hpp"
|
... | ... | |
120 |
119 |
|
121 |
120 |
io_->read(data, TAG_SIZE * 3);
|
122 |
121 |
uint64_t filesize = Exiv2::getULong(data + 4, littleEndian);
|
123 |
|
// uint64_t endoffile = 12;
|
|
122 |
uint64_t endoffile = 12;
|
124 |
123 |
|
125 |
124 |
/* Set up header */
|
126 |
125 |
if (outIo.write(data, TAG_SIZE * 3) != TAG_SIZE * 3)
|
127 |
126 |
throw Error(21);
|
128 |
127 |
|
129 |
128 |
/* Parse Chunks */
|
|
129 |
bool has_size = false;
|
130 |
130 |
bool has_xmp = false;
|
131 |
131 |
bool has_exif = false;
|
132 |
132 |
bool has_vp8x = false;
|
133 |
133 |
bool has_alpha = false;
|
134 |
134 |
bool has_icc = false;
|
135 |
135 |
|
|
136 |
int height;
|
|
137 |
int width;
|
|
138 |
|
136 |
139 |
byte size_buff[4];
|
137 |
140 |
std::string xmpData;
|
138 |
141 |
Blob blob;
|
... | ... | |
176 |
179 |
uint64_t size = Exiv2::getULong(size_buff, littleEndian);
|
177 |
180 |
DataBuf payload(size);
|
178 |
181 |
io_->read(payload.pData_, payload.size_);
|
|
182 |
|
|
183 |
/* Chunk with color profile. */
|
179 |
184 |
if (equalsWebPTag(chunkId, "ICCP") && !has_alpha) {
|
180 |
185 |
has_icc = true;
|
181 |
186 |
}
|
182 |
|
if (equalsWebPTag(chunkId, "VP8X")) {
|
|
187 |
|
|
188 |
/* Chunk with information about features
|
|
189 |
used in the file. */
|
|
190 |
if (equalsWebPTag(chunkId, "VP8X") && !has_vp8x) {
|
183 |
191 |
has_vp8x = true;
|
184 |
192 |
}
|
185 |
|
#if 0 // May need to verify for alpha for these chunks in the future
|
186 |
|
if (equalsWebPTag(chunkId, "VP8 ") && !has_alpha) {
|
187 |
|
has_alpha = true;
|
|
193 |
if (equalsWebPTag(chunkId, "VP8X") && !has_size) {
|
|
194 |
has_size = true;
|
|
195 |
byte size_buf[4];
|
|
196 |
|
|
197 |
// Fetch width
|
|
198 |
memcpy(&size_buf, &payload.pData_[4], 3);
|
|
199 |
size_buf[3] = 0;
|
|
200 |
width = Exiv2::getULong(size_buf, littleEndian) + 1;
|
|
201 |
|
|
202 |
// Fetch height
|
|
203 |
memcpy(&size_buf, &payload.pData_[7], 3);
|
|
204 |
size_buf[3] = 0;
|
|
205 |
height = Exiv2::getULong(size_buf, littleEndian) + 1;
|
188 |
206 |
}
|
|
207 |
|
|
208 |
/* Chunk with with animation control data. */
|
|
209 |
#ifdef __CHECK_FOR_ALPHA__ // Maybe in the future
|
189 |
210 |
if (equalsWebPTag(chunkId, "ANIM") && !has_alpha) {
|
190 |
211 |
has_alpha = true;
|
191 |
212 |
}
|
192 |
213 |
#endif
|
|
214 |
|
|
215 |
/* Chunk with with lossy image data. */
|
|
216 |
#ifdef __CHECK_FOR_ALPHA__ // Maybe in the future
|
|
217 |
if (equalsWebPTag(chunkId, "VP8 ") && !has_alpha) {
|
|
218 |
has_alpha = true;
|
|
219 |
}
|
|
220 |
#endif
|
|
221 |
if (equalsWebPTag(chunkId, "VP8 ") && !has_size) {
|
|
222 |
has_size = true;
|
|
223 |
byte size_buf[4];
|
|
224 |
|
|
225 |
// Fetch width
|
|
226 |
memcpy(&size_buf, &payload.pData_[6], 2);
|
|
227 |
size_buf[2] = 0;
|
|
228 |
size_buf[3] = 0;
|
|
229 |
width = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
|
|
230 |
|
|
231 |
// Fetch height
|
|
232 |
memcpy(&size_buf, &payload.pData_[8], 2);
|
|
233 |
size_buf[2] = 0;
|
|
234 |
size_buf[3] = 0;
|
|
235 |
height = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
|
|
236 |
}
|
|
237 |
|
|
238 |
/* Chunk with with lossless image data. */
|
193 |
239 |
if (equalsWebPTag(chunkId, "VP8L") && !has_alpha) {
|
194 |
240 |
if ((payload.pData_[5] & 0x10) == 0x10) {
|
195 |
241 |
has_alpha = true;
|
196 |
242 |
}
|
197 |
243 |
}
|
|
244 |
if (equalsWebPTag(chunkId, "VP8L") && !has_size) {
|
|
245 |
has_size = true;
|
|
246 |
byte size_buf_w[2];
|
|
247 |
byte size_buf_h[3];
|
|
248 |
|
|
249 |
// Fetch width
|
|
250 |
memcpy(&size_buf_w, &payload.pData_[1], 2);
|
|
251 |
size_buf_w[1] &= 0x3F;
|
|
252 |
width = Exiv2::getUShort(size_buf_w, littleEndian) + 1;
|
|
253 |
|
|
254 |
// Fetch height
|
|
255 |
memcpy(&size_buf_h, &payload.pData_[2], 3);
|
|
256 |
size_buf_h[0] = ((size_buf_h[0] >> 6) & 0x3) | ((size_buf_h[1] & 0x3F) << 0x2);
|
|
257 |
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xF) << 0x2);
|
|
258 |
height = Exiv2::getUShort(size_buf_h, littleEndian) + 1;
|
|
259 |
}
|
|
260 |
|
|
261 |
/* Chunk with animation frame. */
|
198 |
262 |
if (equalsWebPTag(chunkId, "ANMF") && !has_alpha) {
|
199 |
263 |
if ((payload.pData_[5] & 0x2) == 0x2) {
|
200 |
264 |
has_alpha = true;
|
201 |
265 |
}
|
202 |
266 |
}
|
|
267 |
if (equalsWebPTag(chunkId, "ANMF") && !has_size) {
|
|
268 |
has_size = true;
|
|
269 |
byte size_buf[4];
|
|
270 |
|
|
271 |
// Fetch width
|
|
272 |
memcpy(&size_buf, &payload.pData_[6], 3);
|
|
273 |
size_buf[3] = 0;
|
|
274 |
width = Exiv2::getULong(size_buf, littleEndian) + 1;
|
|
275 |
|
|
276 |
// Fetch height
|
|
277 |
memcpy(&size_buf, &payload.pData_[9], 3);
|
|
278 |
size_buf[3] = 0;
|
|
279 |
height = Exiv2::getULong(size_buf, littleEndian) + 1;
|
|
280 |
}
|
|
281 |
|
|
282 |
/* Chunk with alpha data. */
|
203 |
283 |
if (equalsWebPTag(chunkId, "ALPH") && !has_alpha) {
|
204 |
284 |
has_alpha = true;
|
205 |
285 |
}
|
206 |
286 |
}
|
207 |
287 |
|
|
288 |
std::cout << "VP8X res. size [" << width << "x" << height << "]\n";
|
|
289 |
/* Inject a VP8X chunk if one isn't available. */
|
208 |
290 |
if (!has_vp8x) {
|
209 |
|
inject_VP8X(outIo, has_xmp, has_exif, has_alpha, has_icc);
|
|
291 |
inject_VP8X(outIo, has_xmp, has_exif, has_alpha,
|
|
292 |
has_icc, width, height);
|
210 |
293 |
}
|
211 |
294 |
}
|
212 |
295 |
|
... | ... | |
448 |
575 |
|
449 |
576 |
if (equalsWebPTag(chunkId, "VP8X") && !has_canvas_data) {
|
450 |
577 |
has_canvas_data = true;
|
451 |
|
io_->read(payload.pData_, payload.size_);
|
452 |
578 |
byte size_buf[4];
|
|
579 |
|
|
580 |
io_->read(payload.pData_, payload.size_);
|
|
581 |
|
|
582 |
// Fetch width
|
453 |
583 |
memcpy(&size_buf, &payload.pData_[4], 3);
|
454 |
584 |
size_buf[3] = 0;
|
455 |
585 |
pixelWidth_ = Exiv2::getULong(size_buf, littleEndian) + 1;
|
|
586 |
|
|
587 |
// Fetch height
|
456 |
588 |
memcpy(&size_buf, &payload.pData_[7], 3);
|
457 |
589 |
size_buf[3] = 0;
|
458 |
590 |
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
|
... | ... | |
460 |
592 |
has_canvas_data = true;
|
461 |
593 |
io_->read(payload.pData_, payload.size_);
|
462 |
594 |
byte size_buf[4];
|
|
595 |
|
|
596 |
// Fetch width""
|
463 |
597 |
memcpy(&size_buf, &payload.pData_[6], 2);
|
464 |
598 |
size_buf[2] = 0;
|
465 |
599 |
size_buf[3] = 0;
|
466 |
600 |
pixelWidth_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
|
|
601 |
|
|
602 |
// Fetch height
|
467 |
603 |
memcpy(&size_buf, &payload.pData_[8], 2);
|
468 |
604 |
size_buf[2] = 0;
|
469 |
605 |
size_buf[3] = 0;
|
470 |
606 |
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
|
471 |
607 |
} else if (equalsWebPTag(chunkId, "VP8L") && !has_canvas_data) {
|
472 |
608 |
has_canvas_data = true;
|
473 |
|
io_->read(payload.pData_, payload.size_);
|
474 |
609 |
byte size_buf_w[2];
|
|
610 |
byte size_buf_h[3];
|
|
611 |
|
|
612 |
io_->read(payload.pData_, payload.size_);
|
|
613 |
|
|
614 |
// Fetch width
|
475 |
615 |
memcpy(&size_buf_w, &payload.pData_[1], 2);
|
476 |
616 |
size_buf_w[1] &= 0x3F;
|
477 |
617 |
pixelWidth_ = Exiv2::getUShort(size_buf_w, littleEndian) + 1;
|
478 |
|
byte size_buf_h[3];
|
|
618 |
|
|
619 |
// Fetch height
|
479 |
620 |
memcpy(&size_buf_h, &payload.pData_[2], 3);
|
480 |
|
size_buf_h[0] = ((size_buf_h[0] >> 6) & 0x3) | ((size_buf_h[1] & 0x3F) << 0x2);
|
481 |
|
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0x3F) << 0x2);
|
|
621 |
size_buf_h[0] = ((size_buf_h[0] >> 6) & 0x3) | ((size_buf_h[1] & 0x3F) << 0x2);
|
|
622 |
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xF) << 0x2);
|
482 |
623 |
pixelHeight_ = Exiv2::getUShort(size_buf_h, littleEndian) + 1;
|
483 |
624 |
} else if (equalsWebPTag(chunkId, "ANMF") && !has_canvas_data) {
|
484 |
625 |
has_canvas_data = true;
|
485 |
|
io_->read(payload.pData_, payload.size_);
|
486 |
626 |
byte size_buf[4];
|
|
627 |
|
|
628 |
io_->read(payload.pData_, payload.size_);
|
|
629 |
|
|
630 |
// Fetch width
|
487 |
631 |
memcpy(&size_buf, &payload.pData_[6], 3);
|
488 |
632 |
size_buf[3] = 0;
|
489 |
633 |
pixelWidth_ = Exiv2::getULong(size_buf, littleEndian) + 1;
|
|
634 |
|
|
635 |
// Fetch height
|
490 |
636 |
memcpy(&size_buf, &payload.pData_[9], 3);
|
491 |
637 |
size_buf[3] = 0;
|
492 |
638 |
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
|
... | ... | |
574 |
720 |
return image;
|
575 |
721 |
}
|
576 |
722 |
|
577 |
|
bool isWebPType(BasicIo& iIo, bool /*advance*/)
|
|
723 |
bool isWebPType(BasicIo& iIo, bool /*advance*/)
|
578 |
724 |
{
|
579 |
725 |
const int32_t len = 4;
|
580 |
726 |
const unsigned char RiffImageId[4] = { 'R', 'I', 'F' ,'F'};
|
... | ... | |
616 |
762 |
*/
|
617 |
763 |
void WebPImage::inject_VP8X(BasicIo& iIo, bool has_xmp,
|
618 |
764 |
bool has_exif, bool has_alpha,
|
619 |
|
bool has_icc) {
|
|
765 |
bool has_icc, int width, int height) {
|
620 |
766 |
byte header[4];
|
621 |
767 |
byte size[4] = { 0x0A, 0x00, 0x00, 0x00 };
|
622 |
768 |
byte data[10] = { 0x00, 0x00, 0x00, 0x00, 0x00,
|
... | ... | |
642 |
788 |
}
|
643 |
789 |
|
644 |
790 |
/* set width */
|
645 |
|
int w = pixelWidth_- 1;
|
|
791 |
int w = width - 1;
|
646 |
792 |
data[4] = w & 0xFF;
|
647 |
793 |
data[5] = (w >> 8) & 0xFF;
|
648 |
794 |
data[6] = (w >> 16) & 0xFF;
|
649 |
795 |
|
650 |
796 |
/* set width */
|
651 |
|
int h = pixelHeight_- 1;
|
|
797 |
int h = height - 1;
|
652 |
798 |
data[7] = h & 0xFF;
|
653 |
799 |
data[8] = (h >> 8) & 0xFF;
|
654 |
800 |
data[9] = (h >> 16) & 0xFF;
|
655 |
|
-- exiv2-svn/include/exiv2/webpimage.hpp 2016-08-10 17:55:41.717850199 -0400
|
|
801 |
++ exiv2-0.25/include/exiv2/webpimage.hpp 2016-08-10 16:34:29.979442915 -0400
|
... | ... | |
94 |
94 |
bool equalsWebPTag(Exiv2::DataBuf& buf ,const char* str);
|
95 |
95 |
void decodeChunks(uint64_t filesize);
|
96 |
96 |
void inject_VP8X(BasicIo& iIo, bool has_xmp, bool has_exif,
|
97 |
|
bool has_alpha, bool has_icc);
|
|
97 |
bool has_alpha, bool has_icc, int width,
|
|
98 |
int height);
|
98 |
99 |
|
99 |
100 |
//! Copy constructor
|
100 |
101 |
WebPImage(const WebPImage& rhs);
|