libenigma_gdi_a_SOURCES = \
region.cpp grc.cpp epng.cpp erect.cpp fb.cpp font.cpp font_arabic.cpp gfbdc.cpp \
- glcddc.cpp gpixmap.cpp lcd.cpp gfont.cpp accel.cpp
+ glcddc.cpp gpixmap.cpp lcd.cpp gfont.cpp accel.cpp picload.cpp picexif.cpp
# ati/2dablt.cpp ati/2dcore.cpp ati/ati_core.cpp ati/test.cpp ati/2dutil.cpp
--- /dev/null
+#include "picexif.h"
+
+#define M_SOF0 0xC0
+#define M_SOF1 0xC1
+#define M_SOF2 0xC2
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8
+#define M_EOI 0xD9
+#define M_SOS 0xDA
+#define M_JFIF 0xE0
+#define M_EXIF 0xE1
+#define M_COM 0xFE
+
+#define NUM_FORMATS 12
+#define FMT_BYTE 1
+#define FMT_STRING 2
+#define FMT_USHORT 3
+#define FMT_ULONG 4
+#define FMT_URATIONAL 5
+#define FMT_SBYTE 6
+#define FMT_UNDEFINED 7
+#define FMT_SSHORT 8
+#define FMT_SLONG 9
+#define FMT_SRATIONAL 10
+#define FMT_SINGLE 11
+#define FMT_DOUBLE 12
+
+#define TAG_EXIF_VERSION 0x9000
+#define TAG_EXIF_OFFSET 0x8769
+#define TAG_INTEROP_OFFSET 0xa005
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+#define TAG_ORIENTATION 0x0112
+#define TAG_XRESOLUTION 0x011A
+#define TAG_YRESOLUTION 0x011B
+#define TAG_RESOLUTIONUNIT 0x0128
+#define TAG_EXPOSURETIME 0x829A
+#define TAG_FNUMBER 0x829D
+#define TAG_SHUTTERSPEED 0x9201
+#define TAG_APERTURE 0x9202
+#define TAG_BRIGHTNESS 0x9203
+#define TAG_MAXAPERTURE 0x9205
+#define TAG_FOCALLENGTH 0x920A
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_USERCOMMENT 0x9286
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_FLASH 0x9209
+#define TAG_FOCALPLANEXRES 0xa20E
+#define TAG_FOCALPLANEYRES 0xa20F
+#define TAG_FOCALPLANEUNITS 0xa210
+#define TAG_EXIF_IMAGEWIDTH 0xA002
+#define TAG_EXIF_IMAGELENGTH 0xA003
+#define TAG_EXPOSURE_BIAS 0x9204
+#define TAG_WHITEBALANCE 0x9208
+#define TAG_METERING_MODE 0x9207
+#define TAG_EXPOSURE_PROGRAM 0x8822
+#define TAG_ISO_EQUIVALENT 0x8827
+#define TAG_COMPRESSION_LEVEL 0x9102
+#define TAG_THUMBNAIL_OFFSET 0x0201
+#define TAG_THUMBNAIL_LENGTH 0x0202
+
+
+Cexif::Cexif()
+{
+}
+
+Cexif::~Cexif()
+{
+ //ClearExif();
+}
+
+void Cexif::ClearExif()
+{
+ if(freeinfo)
+ {
+ for(int i=0;i<MAX_SECTIONS;i++)
+ if(Sections[i].Data) free(Sections[i].Data);
+ delete m_exifinfo;
+ freeinfo = false;
+ }
+}
+
+bool Cexif::DecodeExif(const char *filename)
+{
+ FILE * hFile = fopen(filename, "r");
+ if(!hFile) return false;
+
+
+ m_exifinfo = new EXIFINFO;
+ memset(m_exifinfo,0,sizeof(EXIFINFO));
+ freeinfo = true;
+
+ m_szLastError[0]='\0';
+ ExifImageWidth = MotorolaOrder = SectionsRead=0;
+ memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));
+
+ int HaveCom = 0;
+ int a = fgetc(hFile);
+ strcpy(m_szLastError,"EXIF-Data not found");
+
+ if (a != 0xff || fgetc(hFile) != M_SOI) return false;
+
+ for(;;)
+ {
+ int marker = 0;
+ int ll,lh, got, itemlen;
+ unsigned char * Data;
+
+ if (SectionsRead >= MAX_SECTIONS)
+ {
+ strcpy(m_szLastError,"Too many sections in jpg file"); return false;
+ }
+
+ for (a=0;a<7;a++)
+ {
+ marker = fgetc(hFile);
+ if (marker != 0xff) break;
+
+ if (a >= 6)
+ {
+ strcpy(m_szLastError,"too many padding unsigned chars\n"); return false;
+ }
+ }
+
+ if (marker == 0xff)
+ {
+ strcpy(m_szLastError,"too many padding unsigned chars!"); return false;
+ }
+
+ Sections[SectionsRead].Type = marker;
+
+ lh = fgetc(hFile);
+ ll = fgetc(hFile);
+
+ itemlen = (lh << 8) | ll;
+
+ if (itemlen < 2)
+ {
+ strcpy(m_szLastError,"invalid marker"); return false;
+ }
+ Sections[SectionsRead].Size = itemlen;
+
+ Data = (unsigned char *)malloc(itemlen);
+ if (Data == NULL)
+ {
+ strcpy(m_szLastError,"Could not allocate memory"); return false;
+ }
+ Sections[SectionsRead].Data = Data;
+
+
+ Data[0] = (unsigned char)lh;
+ Data[1] = (unsigned char)ll;
+
+ got = fread(Data+2, 1, itemlen-2,hFile);
+ if (got != itemlen-2)
+ {
+ strcpy(m_szLastError,"Premature end of file?"); return false;
+ }
+ SectionsRead += 1;
+
+ switch(marker)
+ {
+ case M_SOS:
+ return true;
+ case M_EOI:
+ printf("No image in jpeg!\n");
+ return false;
+ case M_COM:
+ if (HaveCom)
+ {
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }
+ else
+ {
+ process_COM(Data, itemlen);
+ HaveCom = 1;
+ }
+ break;
+ case M_JFIF:
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ break;
+ case M_EXIF:
+ if (memcmp(Data+2, "Exif", 4) == 0)
+ {
+ m_exifinfo->IsExif = process_EXIF((unsigned char *)Data+2, itemlen);
+ }
+ else
+ {
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }
+ break;
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ process_SOFn(Data, marker);
+ break;
+ default:
+ break;
+ }
+ }
+
+ fclose(hFile);
+ return true;
+}
+
+bool Cexif::process_EXIF(unsigned char * CharBuf, unsigned int length)
+{
+ m_exifinfo->Comments[0] = '\0';
+ ExifImageWidth = 0;
+
+ static const unsigned char ExifHeader[] = "Exif\0\0";
+ if(memcmp(CharBuf+0, ExifHeader,6))
+ {
+ strcpy(m_szLastError,"Incorrect Exif header"); return false;
+ }
+
+ if (memcmp(CharBuf+6,"II",2) == 0) MotorolaOrder = 0;
+ else
+ {
+ if (memcmp(CharBuf+6,"MM",2) == 0) MotorolaOrder = 1;
+ else
+ {
+ strcpy(m_szLastError,"Invalid Exif alignment marker."); return false;
+ }
+ }
+
+ if (Get16u(CharBuf+8) != 0x2a)
+ {
+ strcpy(m_szLastError,"Invalid Exif start (1)"); return false;
+ }
+ int FirstOffset = Get32u(CharBuf+10);
+ if (FirstOffset < 8 || FirstOffset > 16)
+ {
+ strcpy(m_szLastError,"Suspicious offset of first IFD value"); return 0;
+ }
+ unsigned char * LastExifRefd = CharBuf;
+
+ if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd)) return false;
+
+ if (m_exifinfo->FocalplaneXRes != 0)
+ m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);
+
+ return true;
+}
+
+int Cexif::Get16m(void * Short)
+{
+ return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+}
+
+int Cexif::Get16u(void * Short)
+{
+ if (MotorolaOrder)
+ {
+ return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+ }
+ else
+ {
+ return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];
+ }
+}
+
+long Cexif::Get32s(void * Long)
+{
+ if (MotorolaOrder)
+ {
+ return ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16) | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );
+ }
+ else
+ {
+ return ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16) | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );
+ }
+}
+
+unsigned long Cexif::Get32u(void * Long)
+{
+ return (unsigned long)Get32s(Long) & 0xffffffff;
+}
+
+bool Cexif::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP )
+{
+ int de, a, NumDirEntries;
+ unsigned ThumbnailOffset = 0;
+ unsigned ThumbnailSize = 0;
+
+ NumDirEntries = Get16u(DirStart);
+
+ if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength))
+ {
+ strcpy(m_szLastError,"Illegally sized directory"); return 0;
+ }
+
+ for (de=0;de<NumDirEntries;de++)
+ {
+ int Tag, Format, Components;
+ unsigned char * ValuePtr;
+ int BytesCount;
+ unsigned char * DirEntry;
+ DirEntry = DirStart+2+12*de;
+ Tag = Get16u(DirEntry);
+ Format = Get16u(DirEntry+2);
+ Components = Get32u(DirEntry+4);
+
+ if ((Format-1) >= NUM_FORMATS)
+ {
+ strcpy(m_szLastError,"Illegal format code in EXIF dir"); return 0;
+ }
+
+ BytesCount = Components * BytesPerFormat[Format];
+
+ if (BytesCount > 4)
+ {
+ unsigned OffsetVal;
+ OffsetVal = Get32u(DirEntry+8);
+ if (OffsetVal+BytesCount > ExifLength)
+ {
+ strcpy(m_szLastError,"Illegal pointer offset value in EXIF."); return 0;
+ }
+ ValuePtr = OffsetBase+OffsetVal;
+ }
+ else ValuePtr = DirEntry+8;
+
+ if (*LastExifRefdP < ValuePtr+BytesCount) *LastExifRefdP = ValuePtr+BytesCount;
+
+ switch(Tag)
+ {
+ case TAG_MAKE:
+ strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31);
+ break;
+ case TAG_MODEL:
+ strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39);
+ break;
+ case TAG_EXIF_VERSION:
+ strncpy(m_exifinfo->Version,(char*)ValuePtr, 4);
+ break;
+ case TAG_DATETIME_ORIGINAL:
+ strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19);
+ break;
+ case TAG_USERCOMMENT:
+ for (a=BytesCount;;)
+ {
+ a--;
+ if (((char*)ValuePtr)[a] == ' ') ((char*)ValuePtr)[a] = '\0';
+ else break;
+
+ if (a == 0) break;
+ }
+
+ if (memcmp(ValuePtr, "ASCII",5) == 0)
+ {
+ for (a=5;a<10;a++)
+ {
+ char c;
+ c = ((char*)ValuePtr)[a];
+ if (c != '\0' && c != ' ')
+ {
+ strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199);
+ break;
+ }
+ }
+
+ }
+ else strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199);
+ break;
+ case TAG_FNUMBER:
+ m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_APERTURE:
+ case TAG_MAXAPERTURE:
+ if (m_exifinfo->ApertureFNumber == 0)
+ {
+ //m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5);
+ }
+ break;
+ case TAG_BRIGHTNESS:
+ m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_FOCALLENGTH:
+ m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_SUBJECT_DISTANCE:
+ m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_EXPOSURETIME:
+ m_exifinfo->ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_SHUTTERSPEED:
+ if (m_exifinfo->ExposureTime == 0)
+ {
+ //m_exifinfo->ExposureTime = (float) (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2)));
+ }
+ break;
+ case TAG_FLASH:
+ if ((int)ConvertAnyFormat(ValuePtr, Format) & 7) strcpy(m_exifinfo->FlashUsed,"fire");
+ else strcpy(m_exifinfo->FlashUsed,"not fired");
+ break;
+ case TAG_ORIENTATION:
+ m_exifinfo->Orient = (int)ConvertAnyFormat(ValuePtr, Format);
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 1: strcpy(m_exifinfo->Orientation,"Top-Left"); break;
+ case 2: strcpy(m_exifinfo->Orientation,"Top-Right"); break;
+ case 3: strcpy(m_exifinfo->Orientation,"Bottom-Right"); break;
+ case 4: strcpy(m_exifinfo->Orientation,"Bottom-Left"); break;
+ case 5: strcpy(m_exifinfo->Orientation,"Left-Top"); break;
+ case 6: strcpy(m_exifinfo->Orientation,"Right-Top"); break;
+ case 7: strcpy(m_exifinfo->Orientation,"Right-Bottom"); break;
+ case 8: strcpy(m_exifinfo->Orientation,"Left-Bottom"); break;
+ default: strcpy(m_exifinfo->Orientation,"Undefined rotation value");
+ }
+ break;
+ case TAG_EXIF_IMAGELENGTH:
+ case TAG_EXIF_IMAGEWIDTH:
+ a = (int)ConvertAnyFormat(ValuePtr, Format);
+ if (ExifImageWidth < a) ExifImageWidth = a;
+ break;
+ case TAG_FOCALPLANEXRES:
+ m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_FOCALPLANEYRES:
+ m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_RESOLUTIONUNIT:
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 2: strcpy(m_exifinfo->ResolutionUnit,"inches"); break;
+ case 3: strcpy(m_exifinfo->ResolutionUnit,"centimeters"); break;
+ default: strcpy(m_exifinfo->ResolutionUnit,"reserved");
+ }
+ break;
+ case TAG_FOCALPLANEUNITS:
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 1: m_exifinfo->FocalplaneUnits = 1.0f; break;
+ case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
+ case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break;
+ case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break;
+ case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f;
+ }
+ break;
+ case TAG_EXPOSURE_BIAS:
+ m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_WHITEBALANCE:
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 0: strcpy(m_exifinfo->LightSource,"unknown"); break;
+ case 1: strcpy(m_exifinfo->LightSource,"Daylight"); break;
+ case 2: strcpy(m_exifinfo->LightSource,"Fluorescent"); break;
+ case 3: strcpy(m_exifinfo->LightSource,"Tungsten"); break;
+ case 17: strcpy(m_exifinfo->LightSource,"Standard light A"); break;
+ case 18: strcpy(m_exifinfo->LightSource,"Standard light B"); break;
+ case 19: strcpy(m_exifinfo->LightSource,"Standard light C"); break;
+ case 20: strcpy(m_exifinfo->LightSource,"D55"); break;
+ case 21: strcpy(m_exifinfo->LightSource,"D65"); break;
+ case 22: strcpy(m_exifinfo->LightSource,"D75"); break;
+ default: strcpy(m_exifinfo->LightSource,"other"); break;
+ }
+ break;
+ case TAG_METERING_MODE:
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 0: strcpy(m_exifinfo->MeteringMode,"unknown"); break;
+ case 1: strcpy(m_exifinfo->MeteringMode,"Average"); break;
+ case 2: strcpy(m_exifinfo->MeteringMode,"Center-Weighted-Average"); break;
+ case 3: strcpy(m_exifinfo->MeteringMode,"Spot"); break;
+ case 4: strcpy(m_exifinfo->MeteringMode,"MultiSpot"); break;
+ case 5: strcpy(m_exifinfo->MeteringMode,"Pattern"); break;
+ case 6: strcpy(m_exifinfo->MeteringMode,"Partial"); break;
+ default: strcpy(m_exifinfo->MeteringMode,"other"); break;
+ }
+ break;
+ case TAG_EXPOSURE_PROGRAM:
+ switch((int)ConvertAnyFormat(ValuePtr, Format))
+ {
+ case 0: strcpy(m_exifinfo->ExposureProgram,"not defined"); break;
+ case 1: strcpy(m_exifinfo->ExposureProgram,"Manual"); break;
+ case 2: strcpy(m_exifinfo->ExposureProgram,"Normal program"); break;
+ case 3: strcpy(m_exifinfo->ExposureProgram,"Aperture priority"); break;
+ case 4: strcpy(m_exifinfo->ExposureProgram,"Shutter priority"); break;
+ case 5: strcpy(m_exifinfo->ExposureProgram,"Creative program"); break;
+ case 6: strcpy(m_exifinfo->ExposureProgram,"Action program"); break;
+ case 7: strcpy(m_exifinfo->ExposureProgram,"Portrait mode"); break;
+ case 8: strcpy(m_exifinfo->ExposureProgram,"Landscape mode"); break;
+ default: strcpy(m_exifinfo->ExposureProgram,"reserved"); break;
+ }
+ break;
+ case TAG_ISO_EQUIVALENT:
+ m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
+ if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
+ break;
+ case TAG_COMPRESSION_LEVEL:
+ m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_XRESOLUTION:
+ m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_YRESOLUTION:
+ m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_THUMBNAIL_OFFSET:
+ ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_THUMBNAIL_LENGTH:
+ ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ }
+
+ if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET)
+ {
+ unsigned char * SubdirStart;
+ SubdirStart = OffsetBase + Get32u(ValuePtr);
+ if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength)
+ {
+ strcpy(m_szLastError,"Illegal subdirectory link"); return 0;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
+ continue;
+ }
+ }
+
+
+ unsigned char * SubdirStart;
+ unsigned Offset;
+ Offset = Get16u(DirStart+2+12*NumDirEntries);
+ if (Offset)
+ {
+ SubdirStart = OffsetBase + Offset;
+ if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength)
+ {
+ strcpy(m_szLastError,"Illegal subdirectory link"); return 0;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
+ }
+
+ if (ThumbnailSize && ThumbnailOffset)
+ {
+ if (ThumbnailSize + ThumbnailOffset <= ExifLength)
+ {
+ m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
+ m_exifinfo->ThumbnailSize = ThumbnailSize;
+ }
+ }
+
+ return 1;
+}
+
+double Cexif::ConvertAnyFormat(void * ValuePtr, int Format)
+{
+ double Value = 0;
+
+ switch(Format)
+ {
+ case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
+ case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break;
+ case FMT_USHORT: Value = Get16u(ValuePtr); break;
+ case FMT_ULONG: Value = Get32u(ValuePtr); break;
+ case FMT_URATIONAL:
+ case FMT_SRATIONAL:
+ {
+ int Num = Get32s(ValuePtr);
+ int Den = Get32s(4+(char *)ValuePtr);
+ if (Den == 0) Value = 0;
+ else Value = (double)Num/Den;
+ break;
+ }
+ case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break;
+ case FMT_SLONG: Value = Get32s(ValuePtr); break;
+ case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
+ case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
+ }
+ return Value;
+}
+
+void Cexif::process_COM (const unsigned char * Data, int length)
+{
+ int ch,a;
+ char Comment[MAX_COMMENT+1];
+ int nch=0;
+
+ if (length > MAX_COMMENT) length = MAX_COMMENT;
+
+ for (a=2;a<length;a++)
+ {
+ ch = Data[a];
+ if (ch == '\r' && Data[a+1] == '\n') continue;
+ if ((ch>=0x20) || ch == '\n' || ch == '\t') Comment[nch++] = (char)ch;
+ else Comment[nch++] = '?';
+ }
+ Comment[nch] = '\0';
+ strcpy(m_exifinfo->Comments,Comment);
+}
+
+void Cexif::process_SOFn (const unsigned char * Data, int marker)
+{
+ int data_precision, num_components;
+
+ data_precision = Data[2];
+ m_exifinfo->Height = Get16m((void*)(Data+3));
+ m_exifinfo->Width = Get16m((void*)(Data+5));
+ num_components = Data[7];
+
+ if (num_components == 3) strcpy(m_exifinfo->IsColor,"yes");
+ else strcpy(m_exifinfo->IsColor,"no");
+
+ m_exifinfo->Process = marker;
+}
+
--- /dev/null
+#ifndef __exif_h__
+#define __exif_h__
+
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <stdio.h>
+
+#define MAX_COMMENT 1000
+#define MAX_SECTIONS 20
+
+
+typedef struct tag_ExifInfo {
+ char Version [5];
+ char CameraMake [32];
+ char CameraModel [40];
+ char DateTime [20];
+ char Orientation [20];
+ char MeteringMode [30];
+ char Comments[MAX_COMMENT];
+ char FlashUsed [20];
+ char IsColor [5];
+ char ResolutionUnit [20];
+ char ExposureProgram[30];
+ char LightSource [20];
+ float Xresolution;
+ float Yresolution;
+ float Brightness;
+ float ExposureTime;
+ float ExposureBias;
+ float Distance;
+ float CCDWidth; //in milimeters
+ float FocalplaneXRes;
+ float FocalplaneYRes;
+ float FocalplaneUnits;
+ float FocalLength;
+ float ApertureFNumber;
+ int Height, Width;
+ int CompressionLevel;
+ int ISOequivalent;
+ int Process;
+ int Orient;
+ unsigned char * ThumbnailPointer;
+ unsigned ThumbnailSize;
+ bool IsExif;
+} EXIFINFO;
+
+static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+
+class Cexif
+{
+ typedef struct tag_Section_t{
+ unsigned char* Data;
+ int Type;
+ unsigned Size;
+ } Section_t;
+public:
+ EXIFINFO* m_exifinfo;
+ char m_szLastError[256];
+ Cexif();
+ ~Cexif();
+ bool DecodeExif(const char *filename);
+ void ClearExif();
+protected:
+ bool process_EXIF(unsigned char * CharBuf, unsigned int length);
+ void process_COM (const unsigned char * Data, int length);
+ void process_SOFn (const unsigned char * Data, int marker);
+ int Get16u(void * Short);
+ int Get16m(void * Short);
+ long Get32s(void * Long);
+ unsigned long Get32u(void * Long);
+ double ConvertAnyFormat(void * ValuePtr, int Format);
+ bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP);
+ int ExifImageWidth;
+ int MotorolaOrder;
+ Section_t Sections[MAX_SECTIONS];
+ int SectionsRead;
+ bool freeinfo;
+};
+
+#endif// __exif_h__
--- /dev/null
+#include "picload.h"
+#include "picexif.h"
+
+#include <png.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" {
+#include <jpeglib.h>
+//#include "transupp.h"
+}
+#include <setjmp.h>
+
+unsigned char *pic_buffer=NULL;
+
+static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
+{
+ unsigned char *cr, *p, *l;
+ int i, j, k, ip;
+ cr = new unsigned char[dx * dy * 3];
+ if (cr == NULL)
+ {
+ printf("[RESIZE] Error: malloc\n");
+ return(orgin);
+ }
+ l = cr;
+
+ for (j = 0; j < dy; j++,l += dx * 3)
+ {
+ p = orgin + (j * oy / dy * ox * 3);
+ for (i = 0, k = 0; i < dx; i++, k += 3)
+ {
+ ip = i * ox / dx * 3;
+ l[k] = p[ip];
+ l[k+1] = p[ip + 1];
+ l[k+2] = p[ip + 2];
+ }
+ }
+ delete [] orgin;
+ return(cr);
+}
+
+static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
+{
+ unsigned char *cr, *p, *q;
+ int i, j, k, l, xa, xb, ya, yb;
+ int sq, r, g, b;
+ cr = new unsigned char[dx * dy * 3];
+ if (cr == NULL)
+ {
+ printf("[RESIZE] Error: malloc\n");
+ return(orgin);
+ }
+ p = cr;
+
+ for (j = 0; j < dy; j++)
+ {
+ for (i = 0; i < dx; i++, p += 3)
+ {
+ xa = i * ox / dx;
+ ya = j * oy / dy;
+ xb = (i + 1) * ox / dx;
+ if (xb >= ox)
+ xb = ox - 1;
+ yb = (j + 1) * oy / dy;
+ if (yb >= oy)
+ yb = oy - 1;
+ for (l = ya, r = 0, g = 0, b = 0, sq = 0; l <= yb; l++)
+ {
+ q = orgin + ((l * ox + xa) * 3);
+ for (k = xa; k <= xb; k++, q += 3, sq++)
+ {
+ r += q[0]; g += q[1]; b += q[2];
+ }
+ }
+ p[0] = r / sq; p[1] = g / sq; p[2] = b / sq;
+ }
+ }
+ delete [] orgin;
+ return(cr);
+}
+
+//-------------------------------------------------------------------
+
+struct r_jpeg_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf envbuffer;
+};
+
+void jpeg_cb_error_exit(j_common_ptr cinfo)
+{
+ struct r_jpeg_error_mgr *mptr;
+ mptr = (struct r_jpeg_error_mgr *) cinfo->err;
+ (*cinfo->err->output_message) (cinfo);
+ longjmp(mptr->envbuffer, 1);
+}
+
+static int jpeg_save(unsigned char *image_buffer, const char * filename, int quality, int image_height, int image_width)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ FILE * outfile; /* target file */
+ JSAMPROW row_pointer[1];/* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ if ((outfile = fopen(filename, "wb")) == NULL)
+ {
+ eDebug("[JPEG] can't open %s", filename);
+ return -1;
+ }
+ jpeg_stdio_dest(&cinfo, outfile);
+
+ cinfo.image_width = image_width;
+ cinfo.image_height = image_height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE );
+ jpeg_start_compress(&cinfo, TRUE);
+ row_stride = image_width * 3;
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+ jpeg_finish_compress(&cinfo);
+ fclose(outfile);
+ jpeg_destroy_compress(&cinfo);
+ return 0;
+}
+
+
+static int jpeg_load(const char *filename, int *x, int *y)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_decompress_struct *ciptr = &cinfo;
+ struct r_jpeg_error_mgr emgr;
+ FILE *fh;
+
+ if (!(fh = fopen(filename, "rb")))
+ return 0;
+
+ ciptr->err = jpeg_std_error(&emgr.pub);
+ emgr.pub.error_exit = jpeg_cb_error_exit;
+ if (setjmp(emgr.envbuffer) == 1)
+ {
+ jpeg_destroy_decompress(ciptr);
+ fclose(fh);
+ return 0;
+ }
+
+ jpeg_create_decompress(ciptr);
+ jpeg_stdio_src(ciptr, fh);
+ jpeg_read_header(ciptr, TRUE);
+ ciptr->out_color_space = JCS_RGB;
+ ciptr->scale_denom = 1;
+
+ jpeg_start_decompress(ciptr);
+
+ *x=ciptr->output_width;
+ *y=ciptr->output_height;
+
+ if(ciptr->output_components == 3)
+ {
+ JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
+ pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
+ unsigned char *bp = pic_buffer;
+
+ while (ciptr->output_scanline < ciptr->output_height)
+ {
+ jpeg_read_scanlines(ciptr, &lb, 1);
+ memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
+ bp += ciptr->output_width * ciptr->output_components;
+ }
+ }
+ jpeg_finish_decompress(ciptr);
+ jpeg_destroy_decompress(ciptr);
+ fclose(fh);
+ return 1;
+}
+
+//---------------------------------------------------------------------------------------------
+
+#define BMP_TORASTER_OFFSET 10
+#define BMP_SIZE_OFFSET 18
+#define BMP_BPP_OFFSET 28
+#define BMP_RLE_OFFSET 30
+#define BMP_COLOR_OFFSET 54
+
+#define fill4B(a) ((4 - ((a) % 4 )) & 0x03)
+
+static int bmp_load(const char *filename, int *x, int *y)
+{
+ unsigned char buff[4];
+
+ int fd = open(filename, O_RDONLY);
+ if (fd == -1) return 0;
+ if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return 0;
+ read(fd, buff, 4);
+ *x = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ read(fd, buff, 4);
+ *y = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return 0;
+ read(fd, buff, 4);
+ int raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return 0;
+ read(fd, buff, 2);
+ int bpp = buff[0] + (buff[1] << 8);
+
+ //printf("x=%d, y=%d,bpp=%d\n",*x, *y, bpp);
+ pic_buffer = new unsigned char[(*x) * (*y) * 3];
+ unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3;
+
+ switch (bpp)
+ {
+ case 24:
+ {
+ int skip = fill4B((*x) * 3);
+ lseek(fd, raster, SEEK_SET);
+ unsigned char c;
+ for (int i = 0; i < (*y); i++)
+ {
+ read(fd, wr_buffer, (*x) * 3);
+ for (int j = 0; j < (*x) * 3 ; j = j + 3)
+ {
+ c = wr_buffer[j];
+ wr_buffer[j] = wr_buffer[j + 2];
+ wr_buffer[j + 2] = c;
+ }
+ if (skip)
+ read(fd, buff, skip);
+ wr_buffer -= (*x) * 3;
+ }
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ close(fd);
+ return 1;
+}
+
+//---------------------------------------------------------------------------------------------
+
+static int png_load(const char *filename, int *x, int *y)
+{
+ static const png_color_16 my_background = {0, 0, 0, 0, 0};
+
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_uint_32 width, height;
+ unsigned int i;
+ int bit_depth, color_type, interlace_type;
+ int number_passes, pass;
+ png_byte * fbptr;
+ FILE * fh;
+
+ if (!(fh = fopen(filename, "rb"))) return 0;
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (png_ptr == NULL)
+ return 0;
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ fclose(fh);
+ return 0;
+ }
+
+ if (setjmp(png_ptr->jmpbuf))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ fclose(fh);
+ return 0;
+ }
+
+ png_init_io(png_ptr, fh);
+
+ png_read_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_set_palette_to_rgb(png_ptr);
+ png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+ }
+
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ png_set_gray_to_rgb(png_ptr);
+ png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+ }
+
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_ptr);
+
+ if (bit_depth < 8) png_set_packing(png_ptr);
+ if (bit_depth == 16) png_set_strip_16(png_ptr);
+
+ number_passes = png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+ if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
+ {
+ eDebug("[PNG] Error processing");
+ return 0;
+ }
+
+ pic_buffer = new unsigned char[width * height * 3];
+ *x=width;
+ *y=height;
+
+ for(pass = 0; pass < number_passes; pass++)
+ {
+ fbptr = (png_byte *)pic_buffer;
+ for (i = 0; i < height; i++, fbptr += width * 3)
+ png_read_row(png_ptr, fbptr, NULL);
+ }
+ png_read_end(png_ptr, info_ptr);
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ fclose(fh);
+ return 1;
+}
+
+//---------------------------------------------------------------------------------------------
+
+PyObject *getExif(const char *filename)
+{
+ PyObject *list = PyList_New(0);
+ Cexif *m_exif = new Cexif();
+ if(m_exif->DecodeExif(filename))
+ {
+
+ if(m_exif->m_exifinfo->IsExif)
+ {
+ char tmp[256];
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Version));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->CameraMake));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->CameraModel));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->DateTime));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Comments));
+ PyList_Append(list, PyString_FromFormat("%d x %d", m_exif->m_exifinfo->Width, m_exif->m_exifinfo->Height));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Orientation));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->MeteringMode));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->ExposureProgram));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->LightSource));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->FlashUsed));
+ PyList_Append(list, PyString_FromFormat("%d", m_exif->m_exifinfo->CompressionLevel));
+ PyList_Append(list, PyString_FromFormat("%d", m_exif->m_exifinfo->ISOequivalent));
+ sprintf(tmp, "%.2f", m_exif->m_exifinfo->Xresolution);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.2f", m_exif->m_exifinfo->Yresolution);
+ PyList_Append(list, PyString_FromString(tmp));
+ PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->ResolutionUnit));
+ sprintf(tmp, "%.2f", m_exif->m_exifinfo->Brightness);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.5f sec.", m_exif->m_exifinfo->ExposureTime);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.5f", m_exif->m_exifinfo->ExposureBias);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.5f", m_exif->m_exifinfo->Distance);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.5f", m_exif->m_exifinfo->CCDWidth);
+ PyList_Append(list, PyString_FromString(tmp));
+ sprintf(tmp, "%.2f", m_exif->m_exifinfo->ApertureFNumber);
+ PyList_Append(list, PyString_FromString(tmp));
+ }
+ else PyList_Append(list, PyString_FromString(m_exif->m_szLastError));
+
+ m_exif->ClearExif();
+ }
+ else PyList_Append(list, PyString_FromString(m_exif->m_szLastError));
+
+ delete m_exif;
+
+ return list;
+}
+
+//---------------------------------------------------------------------------------------------
+
+int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
+{
+ result = 0;
+ int ox=0, oy=0, imx, imy;
+ pic_buffer=NULL;
+ bool cache=false;
+
+ if(cachefile.length())
+ {
+ cache = true;
+ if(jpeg_load(cachefile.c_str(), &ox, &oy))
+ eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy);
+ }
+
+ if(pic_buffer==NULL)
+ {
+ unsigned int pos = filename.find_last_of(".");
+ if (pos == std::string::npos)
+ pos = filename.length() - 1;
+ std::string ext = filename.substr(pos);
+ std::transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int)) toupper);
+ if(ext == ".JPEG" || ext == ".JPG")
+ jpeg_load(filename.c_str(), &ox, &oy);
+ else if(ext == ".BMP")
+ bmp_load(filename.c_str(), &ox, &oy);
+ else if(ext == ".PNG")
+ png_load(filename.c_str(), &ox, &oy);
+ else
+ {
+ eDebug("[PIC] <format not supportet>");
+ return 0;
+ }
+
+ eDebug("[FULLPIC] x-size=%d, y-size=%d", ox, oy);
+
+ if(pic_buffer==NULL)
+ return 0;
+
+ double aspect_ratio;
+ switch(aspect)
+ {
+ case 1: aspect_ratio = 1.777 / ((double)720/576); break; //16:9
+ case 2: aspect_ratio = 1.600 / ((double)720/576); break; //16:10
+ //case 3: aspect_ratio = 1.250 / ((double)720/576); break; //5:4
+ default: aspect_ratio = 1.333 / ((double)720/576); //4:3
+ }
+
+ if((aspect_ratio * oy * w / ox) <= h)
+ {
+ imx = w;
+ imy = (int)(aspect_ratio*oy*w/ox);
+ }
+ else
+ {
+ imx = (int)((1.0/aspect_ratio)*ox*h/oy);
+ imy = h;
+ }
+
+ if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy);
+ else pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy);
+
+ ox = imx;
+ oy = imy;
+
+ if(cache)
+ {
+ jpeg_save(pic_buffer, cachefile.c_str(), 50, oy, ox);
+ eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy);
+ }
+
+ }
+
+
+ result=new gPixmap(eSize(w, h), 32);
+ gSurface *surface = result->surface;
+ int a=0, b=0;
+ int nc=0, oc=0;
+ int o_y=0, u_y=0, v_x=0, h_x=0;
+ unsigned char clear[4] = {0x00,0x00,0x00,0x00};
+ if(background) clear[3]=0xFF;
+ unsigned char *tmp_buffer = new unsigned char[4];
+
+ if(oy < h)
+ {
+ o_y=(h-oy)/2;
+ u_y=h-oy-o_y;
+ }
+ if(ox < w)
+ {
+ v_x=(w-ox)/2;
+ h_x=w-ox-v_x;
+ }
+
+ //eDebug("o_y=%d u_y=%d v_x=%d h_x=%d", o_y, u_y, v_x, h_x);
+
+ if(oy < h)
+ for(a=0; a<(o_y*ox)+1; a++, nc+=4)
+ {
+ memcpy(tmp_buffer, clear, sizeof(clear));
+ tmp_buffer=((unsigned char *)(surface->data)) + nc;
+ }
+
+ for(a=0; a<oy; a++)
+ {
+ if(ox < w)
+ for(b=0; b<v_x; b++, nc+=4)
+ {
+ memcpy(tmp_buffer, clear, sizeof(clear));
+ tmp_buffer=((unsigned char *)(surface->data)) + nc;
+ }
+
+ for(b=0; b<(ox*3); b+=3, nc+=4)
+ {
+ tmp_buffer[3]=0xFF;
+ tmp_buffer[2]=pic_buffer[oc++];
+ tmp_buffer[1]=pic_buffer[oc++];
+ tmp_buffer[0]=pic_buffer[oc++];
+
+ tmp_buffer=((unsigned char *)(surface->data)) + nc;
+ }
+
+ if(ox < w)
+ for(b=0; b<h_x; b++, nc+=4)
+ {
+ memcpy(tmp_buffer, clear, sizeof(clear));
+ tmp_buffer=((unsigned char *)(surface->data)) + nc;
+ }
+ }
+
+ if(oy < h)
+ for(a=0; a<(u_y*ox)+1; a++, nc+=4)
+ {
+ memcpy(tmp_buffer, clear, sizeof(clear));
+ tmp_buffer=((unsigned char *)(surface->data)) + nc;
+ }
+
+ //eDebug("[PIC] buffer=%d, nc=%d oc=%d ox=%d, oy=%d",w*h*4, nc, oc, ox, oy);
+
+ surface->clut.data=0;
+ surface->clut.colors=0;
+ surface->clut.start=0;
+
+ delete [] pic_buffer;
+
+ return 0;
+}
--- /dev/null
+#ifndef __picload_h__
+#define __picload_h__
+
+#include "Python.h"
+#include <lib/gdi/gpixmap.h>
+#include <lib/gdi/epng.h>
+
+SWIG_VOID(int) loadPic(ePtr<gPixmap> &SWIG_OUTPUT, std::string filename, int x, int y, int aspect, int resize_mode=0, int rotate=0, int background=0, std::string cachefile="");
+PyObject *getExif(const char *filename);
+
+#endif // __picload_h__
#include <lib/gdi/lcd.h>
#include <lib/dvb_ci/dvbci_ui.h>
#include <lib/python/python.h>
+#include <lib/gdi/picexif.h>
+#include <lib/gdi/picload.h>
extern void runMainloop();
extern void quitMainloop(int exit_code);
%include <lib/dvb_ci/dvbci_ui.h>
%include <lib/dvb/db.h>
%include <lib/python/python.h>
+%include <lib/gdi/picexif.h>
+%include <lib/gdi/picload.h>
/************** eptr **************/
%template(eActionMapPtr) ePtr<eActionMap>;