Most binary assets are compressed. Diff tools can't work with compressed assets; you'll have to decompress before diffing. Sometimes they also include checksum information which would invalidate any attempt to merge.
How far do you take the decompression? For raster images, you'll probably have to decompress all the way to bitmap because the same image could have multiple completely different binary representations in a format like png.
How do you diff changes? If we have a raster image and one person changes one thing by a small amount, say increases brightness 1%, this could alter every pixel of the image! How would you detect that change and interleave it with something like a contrast adjustment of 1% that could also change every pixel? Sure, the merger would still have to choose which adjustment goes first if the changes aren't independent, but how would they know that's what changed? I.e. how would the diff tool know that the changes are "brightness +1%" and "contrast +1%" and not some other arbitrary number of adjustments?
I don't think the problem is trivial, but I don't think it's hopeless either. If we can measure a person's pulse and mood with a camera pointed at their face, I'm sure we can come up with a tool that can approximate semantically meaningful diffs of artwork. For image formats like xcf that store parts of the image or the editing history independently, this problem becomes even more tractable.
It's very tractable if you don't insist on the diff reconstructing the target file byte-for-byte. But this would require pretty invasive changes in the version control system, no?
If you change the top-left pixel of a PNG, for example, between the intra prediction and the DEFLATE compression, the new file can be totally different, and to reconstruct it you either hope the destination is using the exact same libpng with the exact same settings, or you have to find a space-efficient way to write down all the arbitrary encoding decisions the format allows.
I don't think those are your scm's business. git is the stupid content tracker, it tracks whatever you push into it.
If I were to make a contrived analogy, how do you know how to diff random arrays of bytes ? Where do you start, where do you stop ? How do you know that "\n" or "\r\n" is some kind of delimiter ? You put that knowledge in "diff" and in your editor, and git stores the raw array of bytes. It's the same with binary content: git doesn't care that you don't deal with UTF-8 characters, it doesn't care that it isn't bounded by newline characters.
If you take things this way, you start to understand that the "diff" tool you use must be appropriate to the content you have, and it's not the scm's business. Now, how exactly would a diff work for images, I have absolutely no idea.
An image diff is pretty simple. If you represent an image as a vector of values, diffing just means subtracting two vectors abs(A-B) and writing out the result into a new image.
template<typename T>
T diff(const T& a, const T& b)
{
auto sz = std::min(a.size(), b.size());
T img(sz, 1);
for (auto i = 0; i < sz; ++i) {
img[i] = std::fabs(a[i] - b[i]);
}
return img;
}
// usage
vector<float> a, b;
a.emplace_back(1.0); b.emplace_back(0.5);
a.emplace_back(1.0); b.emplace_back(0.0);
a.emplace_back(0.5); b.emplace_back(0.5);
auto img = diff(a, b);
write_exr("filename.exr", img);
The resulting image ends up with 0.0 black in pixels that are identical and non-zero values in the pixels that differ. When you look at it in an image viewer only the portions that differ will be visible.
You often need to crank up the gain when the differences are small.
Showing diffs for binary assets doesn't need to include things like "brightness 1%". GitHub currently supports image diffs, they're simply displayed side by side, or on top of each other.
This isn't about showing diffs, it's about merging diffs from two separate changes. The best github can do for that right now is let you choose which one you want to keep, it doesn't let you stack changes to keep work from both committers. For that's you need fine grained explanatory stackable diffs.
How far do you take the decompression? For raster images, you'll probably have to decompress all the way to bitmap because the same image could have multiple completely different binary representations in a format like png.
How do you diff changes? If we have a raster image and one person changes one thing by a small amount, say increases brightness 1%, this could alter every pixel of the image! How would you detect that change and interleave it with something like a contrast adjustment of 1% that could also change every pixel? Sure, the merger would still have to choose which adjustment goes first if the changes aren't independent, but how would they know that's what changed? I.e. how would the diff tool know that the changes are "brightness +1%" and "contrast +1%" and not some other arbitrary number of adjustments?