SimpleMobileTools / Simple-Gallery

A premium app for managing and editing your photos, videos, GIFs without ads
https://www.simplemobiletools.com
GNU General Public License v3.0
3.64k stars 764 forks source link

Support Google MVIMG moving images (motion photos) #1426

Open protist opened 5 years ago

protist commented 5 years ago

My Android (Google) camera app has a function where photos can have an embedded ~2 second video in them, to create a MVIMG file. The Google Photos app allows viewing of the looping video, similar to a gif. It also allows extraction of a single frame to pick the best moment.

I'm not sure if it's beyond the scope of Simple Gallery, but it would be great if it could support this format. (At the moment, it's the only thing preventing me from uninstalling Google Photos.)

tibbi commented 5 years ago

sample file sent by Anon on 3rd August 2019

totti4ever commented 5 years ago

Hey I absolutely second this request plus adding the request to also support Samsung Motion Photos! This is an absolute must-have feature to get all pixel and Samsung (S/+) users to this gallery including my wife :-)

A bit of a technical deep dive on the google technique: https://android.jlelse.eu/working-with-motion-photos-da0aa49b50c Apparently a working solution for Samsung: https://gist.github.com/kmark/67cf6c03753ccab155a5da31b3ccd93e

Having a look at the fruit side of the smartphone market, these live photos are extremely popular, so I guess will the Google and Samsung variants be! Anything else I could do?

microchipster commented 5 years ago

Hi, I also would love to see this feature in the app. I'm not great at java, but I've been using this script to extract the mp4 from the google version of these motion photos. It's quite straightforward in bash:

./mvimg /path/to/MVIMG_some_name.jpg returns a new file /path/to/MVIMG_some_name.mp4.

#!/usr/bin/env bash

set -e

function extract {
    local input_file
    local output_file
    local lines
    local offset

    input_file="$1"
    output_file="$2"

    if [ -f "$output_file" ]; then
        echo "File $output_file exists, so ignoring $input_file"
    else
        # find the offset of the string 'ftypmp42' in the file
        lines="$(grep --only-matching --byte-offset --binary --text ftypmp42 "$input_file" | cut -f 1 -d:)"
        echo "$lines"

        # check that it was only found once in the file.. if not, well script probably needs improvement
        if [ ${#lines[@]} -eq 1 ] &>/dev/null ; then
            # the mp4 begins 3 byte before the string 'ftypmp42'
            line_offset=${lines[0]}
            offset=$((line_offset - 3))

            # extract everything beginning at offset to another file
            tail -c +$offset "$input_file" > "$output_file"
        else
            echo "WARNING: skipping $input_file because the string 'ftypmp42' did not occur exactly once in file"
        fi
    fi
}

for input_file in "$@"; do
    if basename "$input_file" | grep -q -P '^MVIMG.*\.jpg'
    then
        output_file="${input_file/[.]jpg/.mp4}"
        extract "$input_file" "$output_file"
    else
        echo "WARNING: skipping $input_file because its file name does not match MVIMG*jpg pattern"
    fi
done
totti4ever commented 5 years ago

Hey, any chance to push this request?

This is actually something no other app I could find beside Google photos and the Samsung exclusive gallery app. So simple gallery would have a unique feature 🥳

mattyeux commented 3 years ago

Is there a chance that someone adds this feature? The only way someone can see these motion images is with google photos.

tibbi commented 3 years ago

some related commit at https://github.com/dic1911/Simple-Gallery/commit/2c007071fce290febf81df151b36a0d684b56d43

lbdroid commented 2 years ago

some related commit at dic1911@2c00707

That looks like a really bad approach to this. Seems to be scanning stupidly through the file until it finds the string "ftyp" associated with the start of an mp4 file. This is heavy on overhead and unreliable.

The required offsets are stored in the jpeg's EXIF information. MVIMG is actually obsolete. The new versions of gcam don't produce that any more. The current version is ".MP.jpg", and the differences between them are very small.

In MP.jpg version, you're looking for EXIF tags with the string "Directory Item". Here is an example;

$ exiftool -a somefile.MP.jpg | grep "Directory Item"
Directory Item Mime             : image/jpeg
Directory Item Semantic         : Primary
Directory Item Length           : 0
Directory Item Padding          : 0
Directory Item Mime             : video/mp4
Directory Item Semantic         : MotionPhoto
Directory Item Length           : 2518994
Directory Item Padding          : 0

Now if you look there closely, you can see the second instance of "Directory Item Length" (the one after "Directory Item Semantic: MotionPhoto"), that is the length of the mp4 at the end of the file. So the offset of the start of the mp4 will be (FILELENGTH - "Directory Item Length" + 1).

The following script will copy the mp4 into a new file;

#!/bin/bash

VLEN=`exiftool -a $1 | grep MotionPhoto -A1 | grep Length | cut -d\: -f2 | sed -e 's/^[ \t]*//'`
FLEN=`ls -l $1 | cut -d\  -f5`
START=$(($FLEN-$VLEN))
dd bs=$START skip=1 if=$1 of=`echo $1 | sed -e "s/jpg/mp4/"`

MVIMG works exactly the same way, except you're looking for a different EXIF tag, "Micro Video Offset". Example;

$ exiftool -a MVIMG_20200905_120533.jpg | grep "Micro Video Offset"
Micro Video Offset              : 3704050

Separation script;

#!/bin/bash

VLEN=`exiftool -a $1 | grep "Micro Video Offset" | cut -d\: -f2 | sed -e 's/^[ \t]*//'`
FLEN=`ls -l $1 | cut -d\  -f5`
START=$(($FLEN-$VLEN))
dd bs=$START skip=1 if=$1 of=`echo $1 | sed -e "s/jpg/mp4/"`
lbdroid commented 2 years ago

Ideally, SimpleGallery would actually just play the video in a loop, if enabled. Looks like Simple Gallery uses exoplayer. This site has an example about playing MP.jpg/MVIMG using exoplayer; https://medium.com/android-news/working-with-motion-photos-da0aa49b50c

Scroll down to the heading "Playing With ExoPlayer".

linesquarecube commented 2 years ago

Hi there, any update on this feature request? Would really love to see this feature :smiley:! There is another gallery app (Aves) I recently discovered which supports motion pictures. Perhaps the functionality can be implemented in Simple Gallery from there - I really like the layout and simplicity of Simple Gallery much more!

mholt commented 1 year ago

@lbdroid Thank you for your detailed comment. I am a passerby implementing something like this in Go, and found your information useful!

In my testing, scanning the whole file for ftyp bytes (in Go, not Kotlin) took about 2.7ms on average, whereas finding and parsing the EXIF metadata to get the offset only takes about 1.2ms. (Exact performance will depend on the EXIF parser's efficiency.) Indeed, going to the metadata is faster than scanning the whole file -- but only on the order of 1 or 2 ms.

My goal is to support multiple vendors' motion photos, not just Google's.

However, I found that parsing metadata out of different file formats is very complicated. Every vendor does metadata differently and does not usually document it publicly (because why would they? it just has to work with their apps, after all). Even within the same file formats, implementations vary between versions and vendors. For example, Google changed the EXIF tag name they use to indicate the embedded video offset around Android 11 or 12; Samsung uses trailers after the JPG image to embed their motion photo information... oh, and Google puts the metadata in XMP, so I found that different parsers need to be used to get that info. (If you're using something like exiftool -- great, it does that all for you).

But in all the files I've tried so far, scanning the file for ftyp and then reading the video bytes to the end has successfully extracted the video file, even though the initial scan is 2ms slower.

Anyway, I know this issue is primarily about Google motion photos, but Samsung and Apple also have theirs... Apple's is "easy" in the sense that I believe the video is always a separate sidecar file.

If it helps anyone else reading this... after a few days of experimenting, my conclusion is that scanning the file for ftyp is the way to go to support multiple vendor motion photos. It's not as elegant or "correct" perhaps, and I'm sure it'll fail in some cases, but it does seem to be the biggest gain for the lowest amount of code.

anarcat commented 11 months ago

for what it's worth, i have found one other photo gallery which does have support for this, aves. it is a tad more featureful too, which might not fit well with the typical "lean" approach of Simple Mobile Tools, but it was good enough for me!

The only thing I found annoying with the feature is it keeps looping the video instead of stopping to the actual shot...

but that's kind of offtopic here of course...