Home | History | Annotate | Download | only in jhead
      1 //--------------------------------------------------------------------------
      2 //  Process IPTC data and XMP data.
      3 //--------------------------------------------------------------------------
      4 #include "jhead.h"
      5 
      6 // IPTC entry types known to Jhead (there's many more defined)
      7 #define IPTC_RECORD_VERSION         0x00
      8 #define IPTC_SUPLEMENTAL_CATEGORIES 0x14
      9 #define IPTC_KEYWORDS               0x19
     10 #define IPTC_CAPTION                0x78
     11 #define IPTC_AUTHOR                 0x7A
     12 #define IPTC_HEADLINE               0x69
     13 #define IPTC_SPECIAL_INSTRUCTIONS   0x28
     14 #define IPTC_CATEGORY               0x0F
     15 #define IPTC_BYLINE                 0x50
     16 #define IPTC_BYLINE_TITLE           0x55
     17 #define IPTC_CREDIT                 0x6E
     18 #define IPTC_SOURCE                 0x73
     19 #define IPTC_COPYRIGHT_NOTICE       0x74
     20 #define IPTC_OBJECT_NAME            0x05
     21 #define IPTC_CITY                   0x5A
     22 #define IPTC_STATE                  0x5F
     23 #define IPTC_COUNTRY                0x65
     24 #define IPTC_TRANSMISSION_REFERENCE 0x67
     25 #define IPTC_DATE                   0x37
     26 #define IPTC_COPYRIGHT              0x0A
     27 #define IPTC_COUNTRY_CODE           0x64
     28 #define IPTC_REFERENCE_SERVICE      0x2D
     29 #define IPTC_TIME_CREATED           0x3C
     30 #define IPTC_SUB_LOCATION           0x5C
     31 #define IPTC_IMAGE_TYPE             0x82
     32 
     33 //--------------------------------------------------------------------------
     34 //  Process and display IPTC marker.
     35 //
     36 //  IPTC block consists of:
     37 //      - Marker:               1 byte      (0xED)
     38 //      - Block length:         2 bytes
     39 //      - IPTC Signature:       14 bytes    ("Photoshop 3.0\0")
     40 //      - 8BIM Signature        4 bytes     ("8BIM")
     41 //      - IPTC Block start      2 bytes     (0x04, 0x04)
     42 //      - IPTC Header length    1 byte
     43 //      - IPTC header           Header is padded to even length, counting the length byte
     44 //      - Length                4 bytes
     45 //      - IPTC Data which consists of a number of entries, each of which has the following format:
     46 //              - Signature     2 bytes     (0x1C02)
     47 //              - Entry type    1 byte      (for defined entry types, see #defines above)
     48 //              - entry length  2 bytes
     49 //              - entry data    'entry length' bytes
     50 //
     51 //--------------------------------------------------------------------------
     52 void show_IPTC (unsigned char* Data, unsigned int itemlen)
     53 {
     54     const char IptcSig1[] = "Photoshop 3.0";
     55     const char IptcSig2[] = "8BIM";
     56     const char IptcSig3[] = {0x04, 0x04};
     57 
     58     unsigned char * pos    = Data + sizeof(short);   // position data pointer after length field
     59     unsigned char * maxpos = Data+itemlen;
     60     char  headerLen = 0;
     61 
     62     if (itemlen < 25) goto corrupt;
     63 
     64     // Check IPTC signatures
     65     if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig;
     66     pos += sizeof(IptcSig1);      // move data pointer to the next field
     67 
     68     if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig;
     69     pos += sizeof(IptcSig2)-1;          // move data pointer to the next field
     70 
     71     if (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0){
     72 badsig:
     73         if (ShowTags){
     74             ErrNonfatal("IPTC type signature mismatch\n",0,0);
     75         }
     76         return;
     77     }
     78     pos += sizeof(IptcSig3);          // move data pointer to the next field
     79 
     80     if (pos >= maxpos) goto corrupt;
     81 
     82     // IPTC section found
     83 
     84     // Skip header
     85     headerLen = *pos++;                     // get header length and move data pointer to the next field
     86     pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
     87 
     88     if (pos+4 >= maxpos) goto corrupt;
     89 
     90     // Get length (from motorola format)
     91     //length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3);
     92 
     93     pos += 4;                    // move data pointer to the next field
     94 
     95     printf("======= IPTC data: =======\n");
     96 
     97     // Now read IPTC data
     98     while (pos < (Data + itemlen-5)) {
     99         short  signature;
    100         unsigned char   type = 0;
    101         short  length = 0;
    102         char * description = NULL;
    103 
    104         if (pos+5 > maxpos) goto corrupt;
    105 
    106         signature = (*pos << 8) + (*(pos+1));
    107         pos += 2;
    108 
    109         if (signature != 0x1C02){
    110             break;
    111         }
    112 
    113         type    = *pos++;
    114         length  = (*pos << 8) + (*(pos+1));
    115         pos    += 2;                          // Skip tag length
    116 
    117         if (pos+length > maxpos) goto corrupt;
    118         // Process tag here
    119         switch (type) {
    120             case IPTC_RECORD_VERSION:
    121                 printf("Record vers.  : %d\n", (*pos << 8) + (*(pos+1)));
    122                 break;
    123 
    124             case IPTC_SUPLEMENTAL_CATEGORIES:  description = "SuplementalCategories"; break;
    125             case IPTC_KEYWORDS:                description = "Keywords"; break;
    126             case IPTC_CAPTION:                 description = "Caption"; break;
    127             case IPTC_AUTHOR:                  description = "Author"; break;
    128             case IPTC_HEADLINE:                description = "Headline"; break;
    129             case IPTC_SPECIAL_INSTRUCTIONS:    description = "Spec. Instr."; break;
    130             case IPTC_CATEGORY:                description = "Category"; break;
    131             case IPTC_BYLINE:                  description = "Byline"; break;
    132             case IPTC_BYLINE_TITLE:            description = "Byline Title"; break;
    133             case IPTC_CREDIT:                  description = "Credit"; break;
    134             case IPTC_SOURCE:                  description = "Source"; break;
    135             case IPTC_COPYRIGHT_NOTICE:        description = "(C)Notice"; break;
    136             case IPTC_OBJECT_NAME:             description = "Object Name"; break;
    137             case IPTC_CITY:                    description = "City"; break;
    138             case IPTC_STATE:                   description = "State"; break;
    139             case IPTC_COUNTRY:                 description = "Country"; break;
    140             case IPTC_TRANSMISSION_REFERENCE:  description = "OriginalTransmissionReference"; break;
    141             case IPTC_DATE:                    description = "DateCreated"; break;
    142             case IPTC_COPYRIGHT:               description = "(C)Flag"; break;
    143             case IPTC_REFERENCE_SERVICE:       description = "Country Code"; break;
    144             case IPTC_COUNTRY_CODE:            description = "Ref. Service"; break;
    145             case IPTC_TIME_CREATED:            description = "Time Created"; break;
    146             case IPTC_SUB_LOCATION:            description = "Sub Location"; break;
    147             case IPTC_IMAGE_TYPE:              description = "Image type"; break;
    148 
    149             default:
    150                 if (ShowTags){
    151                     printf("Unrecognised IPTC tag: %d\n", type );
    152                 }
    153             break;
    154         }
    155         if (description != NULL) {
    156             char TempBuf[32];
    157             memset(TempBuf, 0, sizeof(TempBuf));
    158             memset(TempBuf, ' ', 14);
    159             memcpy(TempBuf, description, strlen(description));
    160             strcat(TempBuf, ":");
    161             printf("%s %*.*s\n", TempBuf, length, length, pos);
    162         }
    163         pos += length;
    164     }
    165     return;
    166 corrupt:
    167     ErrNonfatal("Pointer corruption in IPTC\n",0,0);
    168 }
    169 
    170 
    171 
    172 //--------------------------------------------------------------------------
    173 // Dump contents of XMP section
    174 //--------------------------------------------------------------------------
    175 void ShowXmp(Section_t XmpSection)
    176 {
    177     unsigned char * Data;
    178     char OutLine[101];
    179     int OutLineChars;
    180     int NonBlank;
    181     unsigned a;
    182     NonBlank = 0;
    183     Data = XmpSection.Data;
    184     OutLineChars = 0;
    185 
    186 
    187     for (a=0;a<XmpSection.Size;a++){
    188         if (Data[a] >= 32 && Data[a] < 128){
    189             OutLine[OutLineChars++] = Data[a];
    190             if (Data[a] != ' ') NonBlank |= 1;
    191         }else{
    192             if (Data[a] != '\n'){
    193                 OutLine[OutLineChars++] = '?';
    194             }
    195         }
    196         if (Data[a] == '\n' || OutLineChars >= 100){
    197             OutLine[OutLineChars] = 0;
    198             if (NonBlank){
    199                 puts(OutLine);
    200             }
    201             NonBlank = (NonBlank & 1) << 1;
    202             OutLineChars = 0;
    203         }
    204     }
    205 }
    206