diff --git a/uppsrc/plugin/jpg/init b/uppsrc/plugin/jpg/init index b5bcb56af..6e10f45fa 100644 --- a/uppsrc/plugin/jpg/init +++ b/uppsrc/plugin/jpg/init @@ -1,7 +1,7 @@ #ifndef _plugin_jpg_icpp_init_stub #define _plugin_jpg_icpp_init_stub #include "Draw/init" -#define BLITZ_INDEX__ FCE5007ECA328A2C1D7B74D02BA609390 +#define BLITZ_INDEX__ F6C2A6C6E2A707C9DA951CEB742219A6F #include "jpgreg.icpp" #undef BLITZ_INDEX__ #endif diff --git a/uppsrc/plugin/jpg/jpg.h b/uppsrc/plugin/jpg/jpg.h index 8749279f7..52c8a7ecd 100644 --- a/uppsrc/plugin/jpg/jpg.h +++ b/uppsrc/plugin/jpg/jpg.h @@ -23,6 +23,8 @@ public: virtual const RasterFormat *GetFormat(); virtual Value GetMetaData(String id); virtual void EnumMetaData(Vector& id_list); + + Image GetExifThumbnail(); }; class JPGEncoder : public StreamRasterEncoder { diff --git a/uppsrc/plugin/jpg/jpgupp.cpp b/uppsrc/plugin/jpg/jpgupp.cpp index b3ea1ecc4..2af41bceb 100644 --- a/uppsrc/plugin/jpg/jpgupp.cpp +++ b/uppsrc/plugin/jpg/jpgupp.cpp @@ -192,6 +192,7 @@ public: void ScanExifData(const char *begin); Value GetMetaData(String id); void EnumMetaData(Vector& id_list); + String GetThumbnail(); private: bool Init(); @@ -212,6 +213,7 @@ private: RGBA palette[256]; VectorMap metadata; + int thumboffset, thumblen; struct jpeg_decompress_struct cinfo; struct jpeg_longjmp_error_mgr jerr; @@ -371,6 +373,53 @@ void JPGRaster::Data::EnumMetaData(Vector& id_list) id_list <<= metadata.GetKeys(); } +String JPGRaster::Data::GetThumbnail() +{ + ScanMetaData(); + String app1 = GetMetaData("APP1"); + if(!app1.GetCount()) + return Null; + const char *begin = ~app1 + 6; + const char *end = app1.End(); + const char *p = begin + Exif32(begin + 4); + if(p + 2 >= end) return Null; + p += Exif16(p) * 12 + 2; + if(p + 4 >= end) return Null; + p = begin + Exif32(p); + if(p <= begin || p + 2 >= end) return Null; + word count = Exif16(p); + p += 2; + dword offset = 0; + dword len = 0; + for(int n = 0; n < count; n++) { + if(p + 12 >= end) Null; + if(Exif32(p + 4) == 1) { + dword val = 0; + switch(Exif16(p + 2)) { + case 4: + case 9: + val = Exif32(p + 8); + break; + case 3: + case 8: + val = Exif16(p + 8); + break; + } + if(val) + switch(Exif16(p)) { + case 0x201: + offset = val; + break; + case 0x202: + len = val; + break; + } + } + p += 12; + } + return offset && len && begin + offset + len < end ? String(begin + offset, len) : String(); +} + bool JPGRaster::Data::Init() { if(setjmp(jerr.jmpbuf)) @@ -619,4 +668,10 @@ void JPGEncoder::WriteLineRaw(const byte *s) data->WriteLineRaw(s); } +Image JPGRaster::GetExifThumbnail() +{ + ASSERT(data); + return StreamRaster::LoadStringAny(data->GetThumbnail()); +} + END_UPP_NAMESPACE