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

#include "src/codec/SkPngCodecBase.h"

#include <algorithm>
#include <cstddef>
#include <tuple>
#include <utility>

#include "include/codec/SkCodec.h"
#include "include/codec/SkEncodedImageFormat.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRect.h"
#include "include/core/SkSpan.h"
#include "include/core/SkStream.h"
#include "include/private/SkAssert.h"
#include "include/private/SkEncodedInfo.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkColorPalette.h"
#include "src/codec/SkSwizzler.h"
#include "src/core/SkMemset.h"
#include "src/core/SkSwizzlePriv.h"

namespace {

constexpr SkColorType kXformSrcColorType = kRGBA_8888_SkColorType;

inline bool needs_premul(SkAlphaType dstAT, SkEncodedInfo::Alpha encodedAlpha) {
    return kPremul_SkAlphaType == dstAT && SkEncodedInfo::kUnpremul_Alpha == encodedAlpha;
}

skcms_PixelFormat ToPixelFormat(const SkEncodedInfo& info) {
    // We use kRGB and kRGBA formats because color PNGs are always RGB or RGBA.
    if (16 == info.bitsPerComponent()) {
        if (SkEncodedInfo::kRGBA_Color == info.color()) {
            return skcms_PixelFormat_RGBA_16161616BE;
        } else if (SkEncodedInfo::kRGB_Color == info.color()) {
            return skcms_PixelFormat_RGB_161616BE;
        }
    } else if (SkEncodedInfo::kGray_Color == info.color()) {
        return skcms_PixelFormat_G_8;
    }

    return skcms_PixelFormat_RGBA_8888;
}

}  // namespace

SkPngCodecBase::~SkPngCodecBase() = default;

// static
bool SkPngCodecBase::IsPng(const void* buf, size_t len) {
    static constexpr uint8_t kPngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
    if (len < sizeof(kPngSignature)) {
        return false;
    }

    return memcmp(buf, kPngSignature, sizeof(kPngSignature)) == 0;
}

// static
bool SkPngCodecBase::isCompatibleColorProfileAndType(const SkCodecs::ColorProfile* profile,
                                                     SkEncodedInfo::Color color) {
    if (profile) {
        switch (profile->dataSpace()) {
            case SkCodecs::ColorProfile::DataSpace::kCMYK:
                return false;
            case SkCodecs::ColorProfile::DataSpace::kGray:
                if (SkEncodedInfo::kGray_Color != color &&
                    SkEncodedInfo::kGrayAlpha_Color != color) {
                    return false;
                }
                break;
            default:
                break;
        }
    }

    return true;
}

SkPngCodecBase::SkPngCodecBase(SkEncodedInfo&& encodedInfo,
                               std::unique_ptr<SkStream> stream,
                               SkEncodedOrigin origin,
                               sk_sp<SkPngCompositeChunkReader> chunkReader,
                               std::unique_ptr<SkStream> gainmapStream,
                               std::optional<SkGainmapInfo> gainmapInfo)
        : SkCodec(std::move(encodedInfo), ToPixelFormat(encodedInfo), std::move(stream), origin)
        , fPngChunkReader(std::move(chunkReader))
        , fGainmapStream(std::move(gainmapStream))
        , fGainmapInfo(gainmapInfo) {}

SkEncodedImageFormat SkPngCodecBase::onGetEncodedFormat() const {
    return SkEncodedImageFormat::kPNG;
}

SkCodec::Result SkPngCodecBase::initializeXforms(const SkImageInfo& dstInfo,
                                                 const Options& options,
                                                 int frameWidth) {
    if (frameWidth != dstInfo.width() && options.fSubset) {
        return kInvalidParameters;
    }
    fXformWidth = frameWidth;

    {
        uint32_t encodedBitsPerPixel = getEncodedInfo().bitsPerPixel();

        // We assume that `frameWidth` and the encoded format have already been
        // sanitized earlier (preventing overflow in the row bytes calculation).
        SkASSERT_RELEASE(0 < frameWidth);
        SkASSERT_RELEASE(frameWidth < 0xFFFFFF);
        SkASSERT_RELEASE(encodedBitsPerPixel < 128);

        fEncodedRowBytes = SkCodecPriv::ComputeRowBytes(frameWidth, encodedBitsPerPixel);
    }

    // Reset fSwizzler and this->colorXform().  We can't do this in onRewind() because the
    // interlaced scanline decoder may need to rewind.
    fSwizzler.reset(nullptr);

    // If skcms directly supports the encoded PNG format, we should skip format
    // conversion in the swizzler (or skip swizzling altogether).
    bool skipFormatConversion = false;
    switch (this->getEncodedInfo().color()) {
        case SkEncodedInfo::kRGB_Color:
            if (this->getEncodedInfo().bitsPerComponent() != 16) {
                break;
            }
            [[fallthrough]];
        case SkEncodedInfo::kRGBA_Color:
        case SkEncodedInfo::kGray_Color:
            skipFormatConversion = this->colorXform();
            break;
        default:
            break;
    }

    if (skipFormatConversion && !options.fSubset) {
        fXformMode = kColorOnly_XformMode;
    } else {
        if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) {
            if (!this->createColorTable(dstInfo)) {
                return kInvalidInput;
            }
        }

        Result result =
                this->initializeSwizzler(dstInfo, options, skipFormatConversion, frameWidth);
        if (result != kSuccess) {
            return result;
        }
    }

    this->allocateStorage(dstInfo);

    // We can't call `initializeXformParams` here, because `swizzleWidth` may
    // change *after* `onStartIncrementalDecode`
    // (`SkSampledCodec::sampledDecode` first [transitively] calls
    // `onStartIncrementalDecode` and *then* `SkSwizzler::onSetSampleX`).

    return kSuccess;
}

void SkPngCodecBase::initializeXformParams() {
    switch (fXformMode) {
        case kSwizzleOnly_XformMode:
        case kSwizzleColor_XformMode:
            fXformWidth = this->swizzler()->swizzleWidth();
            break;
        case kColorOnly_XformMode:
            SkASSERT_RELEASE(!fSwizzler);
            break;
    }

    {
        // We assume that `fXformWidth` and the destination format have already been
        // sanitized earlier (preventing overflow in the destination row bytes calculation).
        SkASSERT_RELEASE(0 < fXformWidth);
        SkASSERT_RELEASE(fXformWidth < 0xFFFFFF);

        fDstRowSize = SkCodecPriv::ComputeRowBytesBytesPerPixel(fXformWidth,
                                                                this->dstInfo().bytesPerPixel());
    }
}

void SkPngCodecBase::allocateStorage(const SkImageInfo& dstInfo) {
    switch (fXformMode) {
        case kSwizzleOnly_XformMode:
            break;
        case kColorOnly_XformMode:
            // Intentional fall through.  A swizzler hasn't been created yet, but one will
            // be created later if we are sampling.  We'll go ahead and allocate
            // enough memory to swizzle if necessary.
        case kSwizzleColor_XformMode: {
            const int bitsPerPixel = this->getEncodedInfo().bitsPerPixel();

            // If we have more than 8-bits (per component) of precision, we will keep that
            // extra precision.  Otherwise, we will swizzle to RGBA_8888 before transforming.
            const size_t bytesPerPixel = (bitsPerPixel > 32) ? bitsPerPixel / 8 : 4;
            const size_t colorXformBytes = dstInfo.width() * bytesPerPixel;
            fStorage.reset(colorXformBytes);
            break;
        }
    }
}

SkCodec::Result SkPngCodecBase::initializeSwizzler(const SkImageInfo& dstInfo,
                                                   const Options& options,
                                                   bool skipFormatConversion,
                                                   int frameWidth) {
    SkImageInfo swizzlerInfo = dstInfo;
    Options swizzlerOptions = options;
    fXformMode = kSwizzleOnly_XformMode;
    if (this->colorXform() && this->xformOnDecode()) {
        if (SkEncodedInfo::kGray_Color == this->getEncodedInfo().color()) {
            swizzlerInfo = swizzlerInfo.makeColorType(kGray_8_SkColorType);
        } else {
            swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
        }
        if (kPremul_SkAlphaType == dstInfo.alphaType()) {
            swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
        }

        fXformMode = kSwizzleColor_XformMode;

        // Here, we swizzle into temporary memory, which is not zero initialized.
        // FIXME (msarett):
        // Is this a problem?
        swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized;
    }

    SkIRect frameRect = SkIRect::MakeWH(frameWidth, 1);
    const SkIRect* frameRectPtr = nullptr;
    if (options.fSubset) {
        SkASSERT_RELEASE(frameWidth == dstInfo.width());
    } else {
        frameRectPtr = &frameRect;
    }

    if (skipFormatConversion) {
        // We cannot skip format conversion when there is a color table.
        SkASSERT_RELEASE(!fColorTable);
        int srcBPP = 0;
        switch (this->getEncodedInfo().color()) {
            case SkEncodedInfo::kRGB_Color:
                SkASSERT_RELEASE(this->getEncodedInfo().bitsPerComponent() == 16);
                srcBPP = 6;
                break;
            case SkEncodedInfo::kRGBA_Color:
                srcBPP = this->getEncodedInfo().bitsPerComponent() / 2;
                break;
            case SkEncodedInfo::kGray_Color:
                srcBPP = 1;
                break;
            default:
                SkASSERT_RELEASE(false);
                break;
        }
        fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerInfo, swizzlerOptions, frameRectPtr);
    } else {
        const SkPMColor* colors = SkCodecPriv::GetColorPtr(fColorTable.get());
        fSwizzler = SkSwizzler::Make(
                this->getEncodedInfo(), colors, swizzlerInfo, swizzlerOptions, frameRectPtr);
    }

    return !!fSwizzler ? kSuccess : kUnimplemented;
}

SkSampler* SkPngCodecBase::getSampler(bool createIfNecessary) {
    if (fSwizzler || !createIfNecessary) {
        return fSwizzler.get();
    }

    // Ok to ignore `initializeSwizzler`'s result, because if it fails, then
    // `fSwizzler` will be `nullptr` and we want to return `nullptr` upon
    // failure.
    std::ignore = this->initializeSwizzler(
            this->dstInfo(), this->options(), true, this->dstInfo().width());

    return fSwizzler.get();
}

void SkPngCodecBase::applyXformRow(SkSpan<uint8_t> dstRow, SkSpan<const uint8_t> srcRow) {
    SkASSERT_RELEASE(dstRow.size() >= fDstRowSize);
    SkASSERT_RELEASE(srcRow.size() >= fEncodedRowBytes);
    applyXformRow(dstRow.data(), srcRow.data());
}

void SkPngCodecBase::applyXformRow(void* dstRow, const uint8_t* srcRow) {
    switch (fXformMode) {
        case kSwizzleOnly_XformMode:
            fSwizzler->swizzle(dstRow, srcRow);
            break;
        case kColorOnly_XformMode:
            this->applyColorXform(dstRow, srcRow, fXformWidth);
            break;
        case kSwizzleColor_XformMode:
            SkASSERT_RELEASE(fSwizzler->swizzleWidth() == fXformWidth);
            fSwizzler->swizzle(fStorage.get(), srcRow);
            this->applyColorXform(dstRow, fStorage.get(), fXformWidth);
            break;
    }
}

// Note: SkColorPalette claims to store SkPMColors, which is not necessarily the case here.
bool SkPngCodecBase::createColorTable(const SkImageInfo& dstInfo) {
    if (fDstInfoOfPreviousColorTableCreation.has_value() &&
        *fDstInfoOfPreviousColorTableCreation == dstInfo) {
        return !!fColorTable;
    }
    fColorTable.reset();
    fDstInfoOfPreviousColorTableCreation = dstInfo;

    std::optional<SkSpan<const PaletteColorEntry>> maybePlteChunk = this->onTryGetPlteChunk();
    if (!maybePlteChunk.has_value()) {
        return false;
    }
    const PaletteColorEntry* palette = maybePlteChunk->data();
    constexpr size_t kMaxCountOfPaletteEntries = 256;
    size_t numColors = maybePlteChunk->size();
    numColors = std::min(numColors, kMaxCountOfPaletteEntries);

    // Contents depend on tableColorType and our choice of if/when to premultiply:
    // { kPremul, kUnpremul, kOpaque } x { RGBA, BGRA }
    SkPMColor colorTable[kMaxCountOfPaletteEntries];
    SkColorType tableColorType = this->colorXform() ? kXformSrcColorType : dstInfo.colorType();

    std::optional<SkSpan<const uint8_t>> maybeTrnsChunk = this->onTryGetTrnsChunk();
    const uint8_t* alphas = nullptr;
    size_t numColorsWithAlpha = 0;
    if (maybeTrnsChunk.has_value()) {
        alphas = maybeTrnsChunk->data();
        numColorsWithAlpha = maybeTrnsChunk->size();
        numColorsWithAlpha = std::min(numColorsWithAlpha, numColors);
    }

    bool shouldApplyColorXformToColorTable = this->colorXform() && !this->xformOnDecode();
    if (alphas) {
        bool premultiply = !shouldApplyColorXformToColorTable &&
                           needs_premul(dstInfo.alphaType(), this->getEncodedInfo().alpha());

        // Choose which function to use to create the color table. If the final destination's
        // colortype is unpremultiplied, the color table will store unpremultiplied colors.
        SkCodecPriv::PackColorProc proc =
                SkCodecPriv::ChoosePackColorProc(premultiply, tableColorType);

        for (size_t i = 0; i < numColorsWithAlpha; i++) {
            // We don't have a function in SkOpts that combines a set of alphas with a set
            // of RGBs.  We could write one, but it's hardly worth it, given that this
            // is such a small fraction of the total decode time.
            colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
            palette++;
        }
    }

    if (numColorsWithAlpha < numColors) {
        // The optimized code depends on a 3-byte png_color struct with the colors
        // in RGB order.  These checks make sure it is safe to use.
        static_assert(3 == sizeof(PaletteColorEntry));
        static_assert(offsetof(PaletteColorEntry, red) == 0);
        static_assert(offsetof(PaletteColorEntry, green) == 1);
        static_assert(offsetof(PaletteColorEntry, blue) == 2);

        if (SkCodecPriv::IsRGBA(tableColorType)) {
            SkOpts::RGB_to_RGB1(colorTable + numColorsWithAlpha,
                                (const uint8_t*)palette,
                                numColors - numColorsWithAlpha);
        } else {
            SkOpts::RGB_to_BGR1(colorTable + numColorsWithAlpha,
                                (const uint8_t*)palette,
                                numColors - numColorsWithAlpha);
        }
    }

    if (shouldApplyColorXformToColorTable) {
        this->applyColorXform(colorTable, colorTable, numColors);
    }

    // Pad the color table with the last color in the table (or black) in the case that
    // invalid pixel indices exceed the number of colors in the table.
    const size_t maxColors = static_cast<size_t>(1) << this->getEncodedInfo().bitsPerComponent();
    if (numColors < maxColors) {
        SkPMColor lastColor = numColors > 0 ? colorTable[numColors - 1] : SK_ColorBLACK;
        SkOpts::memset32(colorTable + numColors, lastColor, maxColors - numColors);
    }

    fColorTable.reset(new SkColorPalette(colorTable, maxColors));
    return true;
}

bool SkPngCodecBase::onGetGainmapCodec(SkGainmapInfo* info,
                                       std::unique_ptr<SkCodec>* gainmapCodec) {
    if (!fGainmapStream) {
        return false;
    }

    sk_sp<const SkData> data = fGainmapStream->getData();
    if (!data) {
        return false;
    }

    if (!SkPngCodecBase::IsPng(data->bytes(), data->size())) {
        return false;
    }

    // The gainmap information lives on the gainmap image itself, so we need to
    // create the gainmap codec first, then check if it has a metadata chunk.
    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec = this->onDecodeGainmap(fGainmapStream->duplicate(), &result);

    if (!codec || result != SkCodec::Result::kSuccess) {
        return false;
    }

    bool hasInfo = codec->onGetGainmapInfo(info);

    if (hasInfo && gainmapCodec) {
        // The ISO gainmap payload does not contain the actual alterative image
        // primaries, so we need to query the ICC profile stored on the gainmap.
        if (info->fGainmapMathColorSpace) {
            const auto* colorProfile = codec->getEncodedInfo().colorProfile();
            if (colorProfile) {
                auto colorSpace = colorProfile->getExactColorSpace();
                if (colorSpace) {
                    info->fGainmapMathColorSpace = std::move(colorSpace);
                }
            }
        }

        *gainmapCodec = std::move(codec);
    }

    return hasInfo;
}

bool SkPngCodecBase::onGetGainmapInfo(SkGainmapInfo* info) {
    if (fGainmapInfo) {
        if (info) {
            *info = *fGainmapInfo;
        }
        return true;
    }

    return false;
}
