/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This program converts an image from stdin (e.g. a JPEG, PNG, etc.) to stdout
// (in the NIA/NIE format, a trivial image file format).
//
// The NIA/NIE file format specification is at:
// https://github.com/google/wuffs/blob/master/doc/spec/nie-spec.md
//
// Pass "-1" or "-first-frame-only" as a command line flag to output NIE (a
// still image) instead of NIA (an animated image). The output format (NIA or
// NIE) depends only on this flag's absence or presence, not on the stdin
// image's format.
//
// There are multiple codec implementations of any given image format. For
// example, as of May 2020, Chromium, Skia and Wuffs each have their own BMP
// decoder implementation. There is no standard "libbmp" that they all share.
// Comparing this program's output (or hashed output) to similar programs in
// other repositories can identify image inputs for which these decoders (or
// different versions of the same decoder) produce different output (pixels).
//
// An equivalent program (using the Chromium image codecs) is at:
// https://crrev.com/c/2210331
//
// An equivalent program (using the Wuffs image codecs) is at:
// https://github.com/google/wuffs/blob/master/example/convert-to-nia/convert-to-nia.c

#include <stdio.h>
#include <string.h>

#include "include/codec/SkCodec.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkData.h"
#include "src/base/SkAutoMalloc.h"

static inline void set_u32le(uint8_t* ptr, uint32_t val) {
    ptr[0] = val >> 0;
    ptr[1] = val >> 8;
    ptr[2] = val >> 16;
    ptr[3] = val >> 24;
}

static inline void set_u64le(uint8_t* ptr, uint64_t val) {
    ptr[0] = val >> 0;
    ptr[1] = val >> 8;
    ptr[2] = val >> 16;
    ptr[3] = val >> 24;
    ptr[4] = val >> 32;
    ptr[5] = val >> 40;
    ptr[6] = val >> 48;
    ptr[7] = val >> 56;
}

static void write_nix_header(uint32_t magicU32le, uint32_t width, uint32_t height) {
    uint8_t data[16];
    set_u32le(data + 0, magicU32le);
    set_u32le(data + 4, 0x346E62FF);  // 4 bytes per pixel non-premul BGRA.
    set_u32le(data + 8, width);
    set_u32le(data + 12, height);
    fwrite(data, 1, 16, stdout);
}

static bool write_nia_duration(uint64_t totalDurationMillis) {
    // Flicks are NIA's unit of time. One flick (frame-tick) is 1 / 705_600_000
    // of a second. See https://github.com/OculusVR/Flicks
    static constexpr uint64_t flicksPerMilli = 705600;
    if (totalDurationMillis > (INT64_MAX / flicksPerMilli)) {
        // Converting from millis to flicks would overflow.
        return false;
    }

    uint8_t data[8];
    set_u64le(data + 0, totalDurationMillis * flicksPerMilli);
    fwrite(data, 1, 8, stdout);
    return true;
}

static void write_nie_pixels(uint32_t width, uint32_t height, const SkBitmap& bm) {
    static constexpr size_t kBufferSize = 4096;
    uint8_t                 buf[kBufferSize];
    size_t                  n = 0;
    for (uint32_t y = 0; y < height; y++) {
        for (uint32_t x = 0; x < width; x++) {
            SkColor c = bm.getColor(x, y);
            buf[n++] = SkColorGetB(c);
            buf[n++] = SkColorGetG(c);
            buf[n++] = SkColorGetR(c);
            buf[n++] = SkColorGetA(c);
            if (n == kBufferSize) {
                fwrite(buf, 1, n, stdout);
                n = 0;
            }
        }
    }
    if (n > 0) {
        fwrite(buf, 1, n, stdout);
    }
}

static void write_nia_padding(uint32_t width, uint32_t height) {
    // 4 bytes of padding when the width and height are both odd.
    if (width & height & 1) {
        uint8_t data[4];
        set_u32le(data + 0, 0);
        fwrite(data, 1, 4, stdout);
    }
}

static void write_nia_footer(int repetitionCount, bool stillImage) {
    uint8_t data[8];
    if (stillImage || (repetitionCount == SkCodec::kRepetitionCountInfinite)) {
        set_u32le(data + 0, 0);
    } else {
        // NIA's loop count and Skia's repetition count differ by one. See
        // https://github.com/google/wuffs/blob/master/doc/spec/nie-spec.md#nii-footer
        set_u32le(data + 0, 1 + repetitionCount);
    }
    set_u32le(data + 4, 0x80000000);
    fwrite(data, 1, 8, stdout);
}

int main(int argc, char** argv) {
    bool firstFrameOnly = false;
    for (int a = 1; a < argc; a++) {
        if ((strcmp(argv[a], "-1") == 0) || (strcmp(argv[a], "-first-frame-only") == 0)) {
            firstFrameOnly = true;
            break;
        }
    }

    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(SkData::MakeFromFILE(stdin)));
    if (!codec) {
        SkDebugf("Decode failed.\n");
        return 1;
    }
    codec->getInfo().makeColorSpace(nullptr);
    SkBitmap bm;
    bm.allocPixels(codec->getInfo());
    size_t bmByteSize = bm.computeByteSize();

    // Cache a frame that future frames may depend on.
    int          cachedFrame = SkCodec::kNoFrame;
    SkAutoMalloc cachedFramePixels;

    uint64_t  totalDurationMillis = 0;
    const int frameCount = codec->getFrameCount();
    if (frameCount == 0) {
        SkDebugf("No frames.\n");
        return 1;
    }
    std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
    bool                            stillImage = frameInfos.size() <= 1;

    for (int i = 0; i < frameCount; i++) {
        SkCodec::Options opts;
        opts.fFrameIndex = i;

        if (!stillImage) {
            int durationMillis = frameInfos[i].fDuration;
            if (durationMillis < 0) {
                SkDebugf("Negative animation duration.\n");
                return 1;
            }
            totalDurationMillis += static_cast<uint64_t>(durationMillis);
            if (totalDurationMillis > INT64_MAX) {
                SkDebugf("Unsupported animation duration.\n");
                return 1;
            }

            if ((cachedFrame != SkCodec::kNoFrame) &&
                (cachedFrame == frameInfos[i].fRequiredFrame) && cachedFramePixels.get()) {
                opts.fPriorFrame = cachedFrame;
                memcpy(bm.getPixels(), cachedFramePixels.get(), bmByteSize);
            }
        }

        if (!firstFrameOnly) {
            if (i == 0) {
                write_nix_header(0x41AFC36E,  // "nïA" magic string as a u32le.
                                 bm.width(), bm.height());
            }

            if (!write_nia_duration(totalDurationMillis)) {
                SkDebugf("Unsupported animation duration.\n");
                return 1;
            }
        }

        const SkCodec::Result result =
            codec->getPixels(codec->getInfo(), bm.getPixels(), bm.rowBytes(), &opts);
        if ((result != SkCodec::kSuccess) && (result != SkCodec::kIncompleteInput)) {
            SkDebugf("Decode frame pixels #%d failed.\n", i);
            return 1;
        }

        // If the next frame depends on this one, store it in cachedFrame. It
        // is possible that we may discard a frame that future frames depend
        // on, but the codec will simply redecode the discarded frame.
        if ((static_cast<size_t>(i + 1) < frameInfos.size()) &&
            (frameInfos[i + 1].fRequiredFrame == i)) {
            cachedFrame = i;
            memcpy(cachedFramePixels.reset(bmByteSize), bm.getPixels(), bmByteSize);
        }

        int width = bm.width();
        int height = bm.height();
        write_nix_header(0x45AFC36E,  // "nïE" magic string as a u32le.
                         width, height);
        write_nie_pixels(width, height, bm);
        if (result == SkCodec::kIncompleteInput) {
            SkDebugf("Incomplete input.\n");
            return 1;
        }
        if (firstFrameOnly) {
            return 0;
        }
        write_nia_padding(width, height);
    }
    write_nia_footer(codec->getRepetitionCount(), stillImage);
    return 0;
}
