"Fossies" - the Fresh Open Source Software Archive

Member "jhead-3.04/iptc.c" (22 Nov 2019, 8801 Bytes) of package /linux/privat/jhead-3.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "iptc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.03_vs_3.04.

    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     unsigned char headerLen = 0;
   61     unsigned char dataLen = 0;
   62 
   63     if (itemlen < 25) goto corrupt;
   64 
   65     // Check IPTC signatures
   66     if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig;
   67     pos += sizeof(IptcSig1);      // move data pointer to the next field
   68 
   69     if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig;
   70     pos += sizeof(IptcSig2)-1;          // move data pointer to the next field
   71 
   72 
   73     while (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0) { // loop on valid Photoshop blocks
   74 
   75         pos += sizeof(IptcSig3); // move data pointer to the Header Length
   76         // Skip header
   77         headerLen = *pos; // get header length and move data pointer to the next field
   78         pos += (headerLen & 0xfe) + 2; // move data pointer to the next field (Header is padded to even length, counting the length byte)
   79 
   80         pos += 3; // move data pointer to length, assume only one byte, TODO: use all 4 bytes
   81 
   82         dataLen = *pos++;
   83         pos += dataLen; // skip data section
   84 
   85         if (memcmp(pos, IptcSig2, sizeof(IptcSig2) - 1) != 0) {
   86             badsig: if (ShowTags) {
   87                 ErrNonfatal("IPTC type signature mismatch\n", 0, 0);
   88             }
   89             return;
   90         }
   91         pos += sizeof(IptcSig2) - 1; // move data pointer to the next field
   92     }
   93 
   94     pos += sizeof(IptcSig3);          // move data pointer to the next field
   95 
   96     if (pos >= maxpos) goto corrupt;
   97 
   98     // IPTC section found
   99 
  100     // Skip header
  101     headerLen = *pos++;                     // get header length and move data pointer to the next field
  102     pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
  103 
  104     if (pos+4 >= maxpos) goto corrupt;
  105 
  106     // Get length (from motorola format)
  107     //length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3);
  108 
  109     pos += 4;                    // move data pointer to the next field
  110 
  111     printf("======= IPTC data: =======\n");
  112 
  113     // Now read IPTC data
  114     while (pos < (Data + itemlen-5)) {
  115         short  signature;
  116         unsigned char   type = 0;
  117         short  length = 0;
  118         const char * description = NULL;
  119 
  120         if (pos+5 > maxpos) goto corrupt;
  121 
  122         signature = (*pos << 8) + (*(pos+1));
  123         pos += 2;
  124 
  125         if (signature != 0x1C01 && signature != 0x1c02) break;
  126 
  127         type    = *pos++;
  128         length  = (*pos << 8) + (*(pos+1));
  129         if (length < 1) goto corrupt;
  130         pos    += 2;                          // Skip tag length
  131 
  132         if (pos+length > maxpos) goto corrupt;
  133         // Process tag here
  134         switch (type) {
  135             case IPTC_RECORD_VERSION:
  136                 printf("Record vers.  : %d\n", (*pos << 8) + (*(pos+1)));
  137                 break;
  138 
  139             case IPTC_SUPLEMENTAL_CATEGORIES:  description = "SuplementalCategories"; break;
  140             case IPTC_KEYWORDS:                description = "Keywords"; break;
  141             case IPTC_CAPTION:                 description = "Caption"; break;
  142             case IPTC_AUTHOR:                  description = "Author"; break;
  143             case IPTC_HEADLINE:                description = "Headline"; break;
  144             case IPTC_SPECIAL_INSTRUCTIONS:    description = "Spec. Instr."; break;
  145             case IPTC_CATEGORY:                description = "Category"; break;
  146             case IPTC_BYLINE:                  description = "Byline"; break;
  147             case IPTC_BYLINE_TITLE:            description = "Byline Title"; break;
  148             case IPTC_CREDIT:                  description = "Credit"; break;
  149             case IPTC_SOURCE:                  description = "Source"; break;
  150             case IPTC_COPYRIGHT_NOTICE:        description = "(C)Notice"; break;
  151             case IPTC_OBJECT_NAME:             description = "Object Name"; break;
  152             case IPTC_CITY:                    description = "City"; break;
  153             case IPTC_STATE:                   description = "State"; break;
  154             case IPTC_COUNTRY:                 description = "Country"; break;
  155             case IPTC_TRANSMISSION_REFERENCE:  description = "OriginalTransmissionReference"; break;
  156             case IPTC_DATE:                    description = "DateCreated"; break;
  157             case IPTC_COPYRIGHT:               description = "(C)Flag"; break;
  158             case IPTC_REFERENCE_SERVICE:       description = "Country Code"; break;
  159             case IPTC_COUNTRY_CODE:            description = "Ref. Service"; break;
  160             case IPTC_TIME_CREATED:            description = "Time Created"; break;
  161             case IPTC_SUB_LOCATION:            description = "Sub Location"; break;
  162             case IPTC_IMAGE_TYPE:              description = "Image type"; break;
  163 
  164             default:
  165                 if (ShowTags){
  166                     printf("Unrecognised IPTC tag: %d\n", type );
  167                 }
  168             break;
  169         }
  170         if (description != NULL) {
  171             char TempBuf[32];
  172             memset(TempBuf, 0, sizeof(TempBuf));
  173             memset(TempBuf, ' ', 14);
  174             memcpy(TempBuf, description, strlen(description));
  175             strcat(TempBuf, ":"); 
  176             printf("%s %*.*s\n", TempBuf, length, length, pos);
  177         }
  178         pos += length;
  179     }
  180     return;
  181 corrupt:
  182     ErrNonfatal("Pointer corruption in IPTC\n",0,0);
  183 }
  184 
  185 
  186 
  187 //--------------------------------------------------------------------------
  188 // Dump contents of XMP section
  189 //--------------------------------------------------------------------------
  190 void ShowXmp(Section_t XmpSection)
  191 {
  192     unsigned char * Data;
  193     char OutLine[101];
  194     int OutLineChars;
  195     int NonBlank;
  196     unsigned a;
  197     NonBlank = 0;
  198     Data = XmpSection.Data;
  199     OutLineChars = 0;
  200 
  201 
  202     for (a=0;a<XmpSection.Size;a++){
  203         if (Data[a] >= 32 && Data[a] < 128){
  204             OutLine[OutLineChars++] = Data[a];
  205             if (Data[a] != ' ') NonBlank |= 1;
  206         }else{
  207             if (Data[a] != '\n'){
  208                 OutLine[OutLineChars++] = '?';
  209             }
  210         }
  211         if (Data[a] == '\n' || OutLineChars >= 100){
  212             OutLine[OutLineChars] = 0;
  213             if (NonBlank){
  214                 puts(OutLine);
  215             }
  216             NonBlank = (NonBlank & 1) << 1;
  217             OutLineChars = 0;
  218         }
  219     }
  220 }