Exemple #1
0
int set_date(const ExifData& exif, char date[])
{
	const ExifData::const_iterator end = exif.end();
	ExifData::const_iterator value = exif.findKey(ExifDateTimeCreated);
	
    if(value == end)
		value = exif.findKey(ExifDateTimeDigitized);
       
	if(value == end)
	    return 1;
	    
	const std::string dateTime = value->value().toString();
	
	if(!dateTime.empty())
	{
		//*date = (char*)realloc(*date, (dateTime.length() + 1) * sizeof(char));
		strcpy(date, const_cast<char*>(dateTime.c_str()));  
	
	    // format gets returned as 'YYYY:MM:DD HH:MM:SS' when it
	    // needs to be 'YYYY-MM-DDTHH:MM:SS' so fix separators
	    char* dateStr = date;
	    
	    if(dateTime.length() > 4 && dateStr[4] != '-')
		    dateStr[4] = '-';
		    
	    if(dateTime.length() > 6 && dateStr[7] != '-')
            dateStr[7] = '-';
            
	    if(dateTime.length() > 10 && dateStr[10] != 'T')
            dateStr[10] = 'T';
	}
		
	return 0;
}
Exemple #2
0
int set_long_value(const ExifData& exif, const ExifKey& key, unsigned int& field)
{
	const ExifData::const_iterator end = exif.end();
	const ExifData::const_iterator value = exif.findKey(key);
	
    if(value == end)
        return -1;
        
	field = value->value().toLong();
	return 0;
}
Exemple #3
0
    WriteMethod ExifParser::encode(
              Blob&     blob,
        const byte*     pData,
              uint32_t  size,
              ByteOrder byteOrder,
        const ExifData& exifData
    )
    {
        ExifData ed = exifData;

        // Delete IFD0 tags that are "not recorded" in compressed images
        // Reference: Exif 2.2 specs, 4.6.8 Tag Support Levels, section A
        static const char* filteredIfd0Tags[] = {
            "Exif.Image.PhotometricInterpretation",
            "Exif.Image.StripOffsets",
            "Exif.Image.RowsPerStrip",
            "Exif.Image.StripByteCounts",
            "Exif.Image.JPEGInterchangeFormat",
            "Exif.Image.JPEGInterchangeFormatLength",
            "Exif.Image.SubIFDs"
        };
        for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfd0Tags); ++i) {
            ExifData::iterator pos = ed.findKey(ExifKey(filteredIfd0Tags[i]));
            if (pos != ed.end()) {
#ifdef DEBUG
                std::cerr << "Warning: Exif tag " << pos->key() << " not encoded\n";
#endif
                ed.erase(pos);
            }
        }

        // Delete IFDs which do not occur in JPEGs
        static const IfdId filteredIfds[] = {
            subImage1Id,
            subImage2Id,
            subImage3Id,
            subImage4Id,
            subImage5Id,
            subImage6Id,
            subImage7Id,
            subImage8Id,
            subImage9Id,
            subThumb1Id,
            panaRawId,
            ifd2Id,
            ifd3Id
        };
        for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfds); ++i) {
#ifdef DEBUG
            std::cerr << "Warning: Exif IFD " << filteredIfds[i] << " not encoded\n";
#endif
            eraseIfd(ed, filteredIfds[i]);
        }

        // IPTC and XMP are stored elsewhere, not in the Exif APP1 segment.
        IptcData emptyIptc;
        XmpData  emptyXmp;

        // Encode and check if the result fits into a JPEG Exif APP1 segment
        MemIo mio1;
        std::auto_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder, 0x00000008, false));
        WriteMethod wm = TiffParserWorker::encode(mio1,
                                                  pData,
                                                  size,
                                                  ed,
                                                  emptyIptc,
                                                  emptyXmp,
                                                  Tag::root,
                                                  TiffMapping::findEncoder,
                                                  header.get(),
                                                  0);
        if (mio1.size() <= 65527) {
            append(blob, mio1.mmap(), mio1.size());
            return wm;
        }

        // If it doesn't fit, remove additional tags

        // Delete preview tags if the preview is larger than 32kB.
        // Todo: Enhance preview classes to be able to write and delete previews and use that instead.
        // Table must be sorted by preview, the first tag in each group is the size
        static const PreviewTags filteredPvTags[] = {
            { pttLen, "Exif.Minolta.ThumbnailLength"                  },
            { pttTag, "Exif.Minolta.ThumbnailOffset"                  },
            { pttLen, "Exif.Minolta.Thumbnail"                        },
            { pttLen, "Exif.NikonPreview.JPEGInterchangeFormatLength" },
            { pttIfd, "NikonPreview"                                  },
            { pttLen, "Exif.Olympus.ThumbnailLength"                  },
            { pttTag, "Exif.Olympus.ThumbnailOffset"                  },
            { pttLen, "Exif.Olympus.ThumbnailImage"                   },
            { pttLen, "Exif.Olympus.Thumbnail"                        },
            { pttLen, "Exif.Olympus2.ThumbnailLength"                 },
            { pttTag, "Exif.Olympus2.ThumbnailOffset"                 },
            { pttLen, "Exif.Olympus2.ThumbnailImage"                  },
            { pttLen, "Exif.Olympus2.Thumbnail"                       },
            { pttLen, "Exif.OlympusCs.PreviewImageLength"             },
            { pttTag, "Exif.OlympusCs.PreviewImageStart"              },
            { pttTag, "Exif.OlympusCs.PreviewImageValid"              },
            { pttLen, "Exif.Pentax.PreviewLength"                     },
            { pttTag, "Exif.Pentax.PreviewOffset"                     },
            { pttTag, "Exif.Pentax.PreviewResolution"                 },
            { pttLen, "Exif.PentaxDng.PreviewLength"                  },
            { pttTag, "Exif.PentaxDng.PreviewOffset"                  },
            { pttTag, "Exif.PentaxDng.PreviewResolution"              },
            { pttLen, "Exif.SamsungPreview.JPEGInterchangeFormatLength" },
            { pttIfd, "SamsungPreview"                                },
            { pttLen, "Exif.Thumbnail.StripByteCounts"                },
            { pttIfd, "Thumbnail"                                     },
            { pttLen, "Exif.Thumbnail.JPEGInterchangeFormatLength"    },
            { pttIfd, "Thumbnail"                                     }
        };
        bool delTags = false;
        ExifData::iterator pos;
        for (unsigned int i = 0; i < EXV_COUNTOF(filteredPvTags); ++i) {
            switch (filteredPvTags[i].ptt_) {
            case pttLen:
                delTags = false;
                pos = ed.findKey(ExifKey(filteredPvTags[i].key_));
                if (pos != ed.end() && sumToLong(*pos) > 32768) {
                    delTags = true;
#ifndef SUPPRESS_WARNINGS
                    EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
#endif
                    ed.erase(pos);
                }
                break;
            case pttTag:
                if (delTags) {
                    pos = ed.findKey(ExifKey(filteredPvTags[i].key_));
                    if (pos != ed.end()) {
#ifndef SUPPRESS_WARNINGS
                        EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
#endif
                        ed.erase(pos);
                    }
                }
                break;
            case pttIfd:
                if (delTags) {
#ifndef SUPPRESS_WARNINGS
                    EXV_WARNING << "Exif IFD " << filteredPvTags[i].key_ << " not encoded\n";
#endif
                    eraseIfd(ed, Internal::groupId(filteredPvTags[i].key_));
                }
                break;
            }
        }

        // Delete unknown tags larger than 4kB and known tags larger than 40kB.
        for (ExifData::iterator pos = ed.begin(); pos != ed.end(); ) {
            if (   (pos->size() > 4096 && pos->tagName().substr(0, 2) == "0x")
                || pos->size() > 40960) {
#ifndef SUPPRESS_WARNINGS
                EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
#endif
                pos = ed.erase(pos);
            }
            else {
                ++pos;
            }
        }

        // Encode the remaining Exif tags again, don't care if it fits this time
        MemIo mio2;
        wm = TiffParserWorker::encode(mio2,
                                      pData,
                                      size,
                                      ed,
                                      emptyIptc,
                                      emptyXmp,
                                      Tag::root,
                                      TiffMapping::findEncoder,
                                      header.get(),
                                      0);
        append(blob, mio2.mmap(), mio2.size());
#ifdef DEBUG
        if (wm == wmIntrusive) {
            std::cerr << "SIZE OF EXIF DATA IS " << std::dec << mio2.size() << " BYTES\n";
        }
        else {
            std::cerr << "SIZE DOESN'T MATTER, NON-INTRUSIVE WRITING USED\n";
        }
#endif
        return wm;

    } // ExifParser::encode
Exemple #4
0
void Exiv2Lib::setWhiteBalanceCoeffsCanon(ExifData& data, float wb[3])
{
    ExifData::const_iterator pos;

    if (*mExifInfo.model == "Canon EOS 300D DIGITAL" ||
        *mExifInfo.model == "Canon EOS DIGITAL REBEL")
    {
        pos = data.findKey(ExifKey("Exif.Canon.WhiteBalanceTable"));

        if (pos != data.end())
        {
            qDebug() << "Reading EOS 300D tags";
            uint16_t* cdata = new uint16_t[pos->size() / 2];
            pos->copy((unsigned char*)cdata, littleEndian);

            wb[0] = cdata[1];
            wb[1] = (cdata[2] + cdata[3]) / 2;
            wb[2] = cdata[4];
            float mx = max3(wb[0], wb[1], wb[2]);

            wb[0] /= mx;
            wb[1] /= mx;
            wb[2] /= mx;

            delete [] cdata;
            return;
        }
    }

    pos = data.findKey(ExifKey("Exif.Canon.ColorData"));

    if (pos != data.end())
    {
        uint8_t*                cdata = new uint8_t[pos->size()];

        struct Canon_ColorData* colorData;
        pos->copy(cdata, littleEndian);
        colorData = (struct Canon_ColorData*)cdata;

        if (*mExifInfo.model == "Canon EOS 350D DIGITAL")     // || EOS 20D
        {
            // optimize with bitshifts later
            //                                    wb[0] = colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[2];
            //                                    wb[1] = ((colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[1]+colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[3])/2);
            //                                    wb[2] = colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[0];
            wb[0] = colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[0];
            wb[1] =
                ((colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[1] +
                colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[2]) / 2);
            wb[2] = colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[3];

            qDebug() << "WB EOS 350D DIGITAL RGGB" << wb[0] << "," << wb[1] <<
                "," << wb[2];
        }
        else if (*mExifInfo.model == "Canon EOS 1D Mark II")     // || 1Ds Mark II
        {
            qDebug() << "Whitebalance info unavailable";
        }
        else if (*mExifInfo.model == "Canon G10")
        {
            qDebug() << "Whitebalance info unavailable";
        }
        else if (*mExifInfo.model == "Canon PowerShot S30")
        {
            wb[0] = colorData->V5.WhiteBalanceTable[WB_AsShot].GRBG[1];
            wb[1] =
                (colorData->V5.WhiteBalanceTable[WB_AsShot].GRBG[0] +
                colorData->V5.WhiteBalanceTable[WB_AsShot].GRBG[3]) / 2;
            wb[2] = colorData->V5.WhiteBalanceTable[WB_AsShot].GRBG[2];
        }
        else if (*mExifInfo.model == "Canon PowerShot S110")
        {
            wb[0] =  colorData->V3.WhiteBalanceTable[WB_AsShot].RGGB[0];
            wb[1] = (colorData->V3.WhiteBalanceTable[WB_AsShot].RGGB[1] +
                colorData->V3.WhiteBalanceTable[WB_AsShot].RGGB[2]) / 2;
            wb[2] =  colorData->V3.WhiteBalanceTable[WB_AsShot].RGGB[3];
        }
        else     // attempt to read at the default position at V4
        {
            qDebug() <<
                "Model unknown, Parsing whitebalance using canon default format";
            qDebug() << "Color data version: " << colorData->V7.version;
            // optimize with bitshifs later
            wb[0] = colorData->V7.WhiteBalanceTable[WB_AsShot].RGGB[0];
            wb[1] =
                (colorData->V7.WhiteBalanceTable[WB_AsShot].RGGB[1] +
                colorData->V7.WhiteBalanceTable[WB_AsShot].RGGB[2]) / 2;
            wb[2] = colorData->V7.WhiteBalanceTable[WB_AsShot].RGGB[3];
        }

        float mx = max3(wb[0], wb[1], wb[2]);

        wb[0] /= mx;
        wb[1] /= mx;
        wb[2] /= mx;

        delete [] cdata;
    }
    else
    {
        //qDebug() << "no such exif key";

        wb[0] = 1.0;
        wb[1] = 1.0;
        wb[2] = 1.0;
    }
    //    qDebug() << "WB RGGB Multipliers" <<wb[0] <<","<<wb[1]<<","<<wb[2];
}
Exemple #5
0
void Exiv2Lib::setWhiteBalanceCoeffsNikon(ExifData& data, float wb[3])
{
    ExifData::const_iterator pos;

    /*
     * This seems to be unnecessary as the multipliers are also
     * available as rational numbers in the WB_RBLevels tag
     */
    /*
       pos = data.findKey(ExifKey("Exif.Nikon3.Version"));

       int makerNoteVersion = -1;

       if (pos != data.end())
       {
           char*   buf =  new char[pos->size()];
           pos->copy((unsigned char*)buf, littleEndian);
           QString val(buf);
           qDebug() << val;
           delete [] buf;

           makerNoteVersion = val.toInt();
       }
       qDebug() << "Nikon makenote version:" << makerNoteVersion;

       if (makerNoteVersion >= 200)
       {
        qDebug() << "Decrypt Nikon Color Balance";
       }

     */
    pos = data.findKey(ExifKey("Exif.Nikon3.WB_RBLevels"));

    if (pos != data.end())
    {
        if (*mExifInfo.model == "NIKON D300")
        {
            wb[0] = 1.0f;
            wb[1] = 1.0f;
            wb[2] = 1.0f;
            //            wb[0] = colorData->V3.WhiteBalanceTable[WB_AsShot].RGGB[0];
            //            wb[1] =
            //                ((colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[1] +
            //                colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[2]) / 2);
            //            wb[2] = colorData->V1.WhiteBalanceTable[WB_AsShot].RGGB[3];
            qDebug() << "White balance for model Nikon D300";

            if (pos != data.end())
            {
                wb[0] = pos->toFloat(0);
                wb[1] = 1.0f;
                wb[2] = pos->toFloat(1);
                qDebug() << "Nikon: RGB" << wb[0] << "," << wb[1] << "," <<
                    wb[2];
            }
        }
        float mx = max3(wb[0], wb[1], wb[2]);

        wb[0] /= mx;
        wb[1] /= mx;
        wb[2] /= mx;
    }
    else
    {
        qDebug () << "Nikon: Color balance data not available";
        wb[0] = 1.0f;
        wb[1] = 1.0f;
        wb[2] = 1.0f;
    }
}