-if with -execute (extracting jpeg previews from raw files)

Started by busywait, December 07, 2017, 07:59:28 AM

Previous topic - Next topic

busywait

Hi, I'm extracting preview images from camera raw files.

There's a working example here:
https://exiftool.org/exiftool_pod.html#COPYING-EXAMPLES

exiftool -if '$jpgfromraw' -b -jpgfromraw -w %d%f_%ue.jpg -execute -if '$previewimage' -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR
QuoteExtract JpgFromRaw or PreviewImage from all but JPG files in DIR, saving them with file names like image_EXT.jpg, then add all meta information from the original files to the extracted images. Here, the command line is broken into three sections (separated by -execute options), and each is executed as if it were a separate command. The -common_args option causes the --ext jpg DIR arguments to be applied to all three commands, and the -srcfile option allows the extracted JPG image to be the source file for the third command (whereas the RAW files are the source files for the other two commands).

While it works, can anyone tell me what the point of the "-if" conditions is? Surely the files will only be created if the respective JpegFromRaw or PreviewImage attributes exist anyway?

Is there anything in that example command that avoids extraction being attempted twice? I think that this simpler version is equivalent:
exiftool -b -jpgfromraw -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR

Edit: I was wrong (nearly right?) see Phil's response below.

Phil Harvey

Good point.  I don't know why I added these -if conditions.  I will remove them from this example, so it will be:

exiftool -b -jpgfromraw -w %d%f_%ue.jpg -execute -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR

Thanks for pointing this out.

While the -if options are not necessary, the images still need to be extracted in separate commands.  Your command will write both into the same file if they both exist.

- Phil

Edit:  Or this could be done to avoid a warning message if both exist:

exiftool -b -jpgfromraw -w %d%f_%ue.jpg -execute -if 'not $jpgfromraw' -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR

Edit2: The way to combine the first 2 commands into 1 is to use a user-defined Composite tag like the "BigImage" tag in the example config file

exiftool -config example.config -b -bigimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

Thank you Phil,

Your revised option looks best, I like to avoid getting warnings :)

Sorry to follow up with more questions:

Is each set of "execute" options guaranteed to run in left to right order?

Is PreviewImage always a jpg format image?

Is JpgFromRaw always "better" than PreviewImage? (Perhaps bigger, or more recently   edited)? My own raw files always have a PreviewImage, but never a JpgFromRaw.


Phil Harvey

Quote from: busywait on December 07, 2017, 09:19:30 AM
Is each set of "execute" options guaranteed to run in left to right order?

Yes.

QuoteIs PreviewImage always a jpg format image?

Yes.

QuoteIs JpgFromRaw always "better" than PreviewImage?

It should be bigger if it exists, but I won't guarantee that.  But the BigImage tag takes the biggest one.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

Quote from: Phil Harvey on December 07, 2017, 09:01:47 AM
Edit2: The way to combine the first 2 commands into 1 is to use a user-defined Composite tag like the "BigImage" tag in the example config file

exiftool -config example.config -b -bigimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original -common_args --ext jpg DIR

Even better, thanks for pointing out the BigImage composite tag in example.config, it looks more robust than the command line, I'll go with that.

As an additional possible preview, some editing software (for example, ACDSee), keeps a cached preview of any edited raw file in a "hidden" subfolder. How could I integrate the content of a file in to BigImage?

Slurp the whole image off disk and push it on to the array @$val?


        # [advanced] select largest JPEG preview image
        BigImage => {
            Groups => { 2 => 'Preview' },
            Desire => {
                0 => 'JpgFromRaw',
                1 => 'PreviewImage',
                2 => 'OtherImage',
                # (DNG and A100 ARW may be have 2 PreviewImage's)
                3 => 'PreviewImage (1)',
            },
            # ValueConv may also be a code reference
            # Inputs: 0) reference to list of values, 1) ExifTool object
            ValueConv => sub {
                my $val = shift;

                # Can I add the content of file '[Devoloped]/%f.%e.jpg' to @$val?

                my ($image, $bigImage, $len, $bigLen);
                foreach $image (@$val) {
                    next unless ref $image eq 'SCALAR';
                    # check for JPEG image (or "Binary data" if -b not used)
                    next unless $$image =~ /^(\xff\xd8\xff|Binary data (\d+))/;
                    $len = $2 || length $$image; # get image length
                    # save largest image
                    next if defined $bigLen and $bigLen >= $len;
                    $bigLen = $len;
                    $bigImage = $image;
                }
                return $bigImage;
            },


Or, am I best sticking to "exiftool -o" for exatracting a copy of those when I want them?


Phil Harvey

It would require some specialized programming to load an external file from a user-defined tag.  Not really how ExifTool is designed.  So I you should handle those separately, maybe be copying with "exiftool -o" as I think you are suggesting.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

In my script I've added a -writeMode cg option, a bit like this:

exiftool -b -jpgfromraw -w %d%f_%ue.jpg -execute -if 'not $jpgfromraw' -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -writeMode cg -overwrite_original -common_args --ext jpg DIR

Because I can't guarantee that the .jpg was created by this command (exiftool does not overwrite images), and I don't want to overwrite values that have been added explicitly, the wriiteMode option will only add tags that do not exist at all.

Maybe that's worth adding to the example doc?

Phil Harvey

Good idea.  Thanks for the suggestion, but I fear that adding the -wm option to that example would make it too complex for even an advanced example.

But maybe I could add an option to not run a command if the previous command returned an error status.  Let me think about this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

Better a complicated example than one that overwrites or misses data perhaps? (And you are about to simplify it by removing an 'if' :) )

"Stop on error" was what I was originally looking for but -writeMode cg covered what I need in this case.

My testing threw up another wrinkle: the most up-to-date metadata is in the .xmp sidecar file if it exists, I only want to copy missing tags from the raw file, or all tags when there is no .xmp.

So I have also now added -tagsFromFile @ -tagsFromFile %d%f.xmp to the command. I think that that is including all the usual tags from the raw file, and with the latest values and any additional tags from the .xmp if any have been set. Is that correct?

exiftool -b -jpgfromraw -w %d%f_%ue.jpg -execute -if 'not $jpgfromraw' -b -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -tagsFromFile %d%f.xmp -srcfile %d%f_%ue.jpg -writeMode cg -overwrite_original -common_args --ext jpg DIR

Phil Harvey

Your new command will read all tags from the raw file, then read all tags from the xmp file (overriding any same-named tags from the raw file), then write only tags that already exist in the jpg.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

Oh dear, that would be almost the opposite of what I wanted :( However, it's not what I see when I test it :)

- Extracted PreviewImage "test_RAW.jpg" has no metadata after extraction (tested separately)
- All appropriate metadata is written in to test_RAW.jpg with the -wm cg option
- If test_RAW.jpg already exists with metadata before running the command then new tags are created if they have been added in the Raw or XMP
- Existing tags in test_RAW.jpg will not be overwritten

Exiftool 10.60.

I used an arg file to test rather than a command line, but the options are the same.





Phil Harvey

Sorry,

I meant this:

Your new command will read all tags from the raw file, then read all tags from the xmp file (overriding any same-named tags from the raw file), then write only tags that don't exist in the jpg.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

busywait

Great, thanks - and that's exactly what I want, and what I'm seeing happen.

There's a warning when the .xmp file doesn't exist, but that's maybe useful ouput to see anyway.