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

#include "include/core/SkBitmap.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkStream.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/encode/SkPngEncoder.h"
#include "include/encode/SkWebpEncoder.h"
#include "include/private/base/SkTFitsIn.h"
#include "include/private/base/SkTo.h"
#include "src/encode/SkImageEncoderPriv.h"
#include "src/image/SkImage_Base.h"
#include "src/ports/SkNDKConversions.h"

static AndroidBitmapInfo info_for_pixmap(const SkPixmap& pmap) {
    // If any of these values is invalid (e.g. set to zero), the info will be rejected by
    // AndroidBitmap_compress.
    AndroidBitmapInfo info {
        .width  = SkTFitsIn<uint32_t>(pmap.width())    ? SkToU32(pmap.width())    : 0,
        .height = SkTFitsIn<uint32_t>(pmap.height())   ? SkToU32(pmap.height())   : 0,
        .stride = SkTFitsIn<uint32_t>(pmap.rowBytes()) ? SkToU32(pmap.rowBytes()) : 0,
        .format = SkNDKConversions::toAndroidBitmapFormat(pmap.colorType()),
        .flags = SkNDKConversions::toAndroidBitmapAlphaFlags(pmap.alphaType())
    };

    return info;
}

static bool write_image_to_stream(SkWStream* stream,
                                  const SkPixmap& pmap,
                                  AndroidBitmapCompressFormat androidFormat,
                                  int quality) {
    AndroidBitmapInfo info = info_for_pixmap(pmap);

    auto write_to_stream = [](void* userContext, const void* data, size_t size) {
        return reinterpret_cast<SkWStream*>(userContext)->write(data, size);
    };

    return ANDROID_BITMAP_RESULT_SUCCESS == AndroidBitmap_compress(&info,
            SkNDKConversions::toDataSpace(pmap.colorSpace()), pmap.addr(), androidFormat, quality,
            reinterpret_cast<void*>(stream), write_to_stream);
}

namespace SkPngEncoder {
std::unique_ptr<SkEncoder> Make(SkWStream*, const SkPixmap&, const Options&) {
    SkDEBUGFAIL("Making an encoder is not supported via the NDK");
    return nullptr;
}

bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options) {
    return write_image_to_stream(dst, src, ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100);
}

sk_sp<SkData> Encode(const SkPixmap& src, const Options& options) {
    SkDynamicMemoryWStream stream;
    return Encode(&stream, src, options) ? stream.detachAsData() : nullptr;
}

sk_sp<SkData> Encode(GrDirectContext* ctx, const SkImage* img, const Options& options) {
    if (!img) {
        return nullptr;
    }
    SkBitmap bm;
    if (!as_IB(img)->getROPixels(ctx, &bm)) {
        return nullptr;
    }
    return Encode(bm.pixmap(), options);
}
}  // namespace SkPngEncoder

namespace SkJpegEncoder {

bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options) {
    return write_image_to_stream(dst, src, ANDROID_BITMAP_COMPRESS_FORMAT_JPEG, options.fQuality);
}

sk_sp<SkData> Encode(const SkPixmap& src, const Options& options) {
    SkDynamicMemoryWStream stream;
    return Encode(&stream, src, options) ? stream.detachAsData() : nullptr;
}

bool Encode(SkWStream*, const SkYUVAPixmaps&, const SkColorSpace*, const Options&) {
    SkDEBUGFAIL("encoding a YUVA pixmap is not supported via the NDK");
    return false;
}

sk_sp<SkData> Encode(GrDirectContext* ctx, const SkImage* img, const Options& options) {
    if (!img) {
        return nullptr;
    }
    SkBitmap bm;
    if (!as_IB(img)->getROPixels(ctx, &bm)) {
        return nullptr;
    }
    return Encode(bm.pixmap(), options);
}

std::unique_ptr<SkEncoder> Make(SkWStream*, const SkPixmap&, const Options&) {
    SkDEBUGFAIL("Making an encoder is not supported via the NDK");
    return nullptr;
}

std::unique_ptr<SkEncoder> Make(SkWStream*,
                                const SkYUVAPixmaps&,
                                const SkColorSpace*,
                                const Options&) {
    SkDEBUGFAIL("Making an encoder is not supported via the NDK");
    return nullptr;
}

}  // namespace SkJpegEncoder

namespace SkWebpEncoder {

bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options) {
    if (options.fCompression == Compression::kLossless) {
        return write_image_to_stream(
                dst, src, ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSLESS, options.fQuality);
    }
    return write_image_to_stream(
            dst, src, ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSY, options.fQuality);
}

sk_sp<SkData> Encode(const SkPixmap& src, const Options& options) {
    SkDynamicMemoryWStream stream;
    return Encode(&stream, src, options) ? stream.detachAsData() : nullptr;
}

sk_sp<SkData> Encode(GrDirectContext* ctx, const SkImage* img, const Options& options) {
    if (!img) {
        return nullptr;
    }
    SkBitmap bm;
    if (!as_IB(img)->getROPixels(ctx, &bm)) {
        return nullptr;
    }
    return Encode(bm.pixmap(), options);
}

bool EncodeAnimated(SkWStream*, SkSpan<const SkEncoder::Frame>, const Options&) {
    SkDEBUGFAIL("Encoding Animated WebP images is not supported with the NDK.");
    return false;
}
}  // namespace SkWebpEncoder
