// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../../include/fpdfapi/fpdf_module.h"
#include "../../../include/fpdfapi/fpdf_page.h"
#include "../../../include/fxcodec/fx_codec.h"
#include "../../../include/fpdfapi/fpdf_render.h"
#include "../fpdf_page/pageint.h"
#include "../fpdf_render/render_int.h"
CPDF_Dictionary* CPDF_Image::InitJPEG(uint8_t* pData, FX_DWORD size) {
  int32_t width;
  int32_t height;
  int32_t num_comps;
  int32_t bits;
  FX_BOOL color_trans;
  if (!CPDF_ModuleMgr::Get()->GetJpegModule()->LoadInfo(
          pData, size, width, height, num_comps, bits, color_trans)) {
    return NULL;
  }
  CPDF_Dictionary* pDict = new CPDF_Dictionary;
  pDict->SetAtName("Type", "XObject");
  pDict->SetAtName("Subtype", "Image");
  pDict->SetAtInteger("Width", width);
  pDict->SetAtInteger("Height", height);
  const FX_CHAR* csname = NULL;
  if (num_comps == 1) {
    csname = "DeviceGray";
  } else if (num_comps == 3) {
    csname = "DeviceRGB";
  } else if (num_comps == 4) {
    csname = "DeviceCMYK";
    CPDF_Array* pDecode = CPDF_Array::Create();
    for (int n = 0; n < 4; n++) {
      pDecode->AddInteger(1);
      pDecode->AddInteger(0);
    }
    pDict->SetAt(FX_BSTRC("Decode"), pDecode);
  }
  pDict->SetAtName("ColorSpace", csname);
  pDict->SetAtInteger("BitsPerComponent", bits);
  pDict->SetAtName("Filter", "DCTDecode");
  if (!color_trans) {
    CPDF_Dictionary* pParms = new CPDF_Dictionary;
    pDict->SetAt("DecodeParms", pParms);
    pParms->SetAtInteger("ColorTransform", 0);
  }
  m_bIsMask = FALSE;
  m_Width = width;
  m_Height = height;
  if (m_pStream == NULL) {
    m_pStream = new CPDF_Stream(NULL, 0, NULL);
  }
  return pDict;
}
void CPDF_Image::SetJpegImage(uint8_t* pData, FX_DWORD size) {
  CPDF_Dictionary* pDict = InitJPEG(pData, size);
  if (!pDict) {
    return;
  }
  m_pStream->InitStream(pData, size, pDict);
}
void CPDF_Image::SetJpegImage(IFX_FileRead* pFile) {
  FX_DWORD size = (FX_DWORD)pFile->GetSize();
  if (!size) {
    return;
  }
  FX_DWORD dwEstimateSize = size;
  if (dwEstimateSize > 8192) {
    dwEstimateSize = 8192;
  }
  uint8_t* pData = FX_Alloc(uint8_t, dwEstimateSize);
  pFile->ReadBlock(pData, 0, dwEstimateSize);
  CPDF_Dictionary* pDict = InitJPEG(pData, dwEstimateSize);
  FX_Free(pData);
  if (!pDict && size > dwEstimateSize) {
    pData = FX_Alloc(uint8_t, size);
    pFile->ReadBlock(pData, 0, size);
    pDict = InitJPEG(pData, size);
    FX_Free(pData);
  }
  if (!pDict) {
    return;
  }
  m_pStream->InitStream(pFile, pDict);
}
void _DCTEncodeBitmap(CPDF_Dictionary* pBitmapDict,
                      const CFX_DIBitmap* pBitmap,
                      int quality,
                      uint8_t*& buf,
                      FX_STRSIZE& size) {}
void _JBIG2EncodeBitmap(CPDF_Dictionary* pBitmapDict,
                        const CFX_DIBitmap* pBitmap,
                        CPDF_Document* pDoc,
                        uint8_t*& buf,
                        FX_STRSIZE& size,
                        FX_BOOL bLossLess) {}
void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap,
                          int32_t iCompress,
                          IFX_FileWrite* pFileWrite,
                          IFX_FileRead* pFileRead,
                          const CFX_DIBitmap* pMask,
                          const CPDF_ImageSetParam* pParam) {
  int32_t BitmapWidth = pBitmap->GetWidth();
  int32_t BitmapHeight = pBitmap->GetHeight();
  if (BitmapWidth < 1 || BitmapHeight < 1) {
    return;
  }
  uint8_t* src_buf = pBitmap->GetBuffer();
  int32_t src_pitch = pBitmap->GetPitch();
  int32_t bpp = pBitmap->GetBPP();
  FX_BOOL bUseMatte =
      pParam && pParam->pMatteColor && (pBitmap->GetFormat() == FXDIB_Argb);
  CPDF_Dictionary* pDict = new CPDF_Dictionary;
  pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject"));
  pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image"));
  pDict->SetAtInteger(FX_BSTRC("Width"), BitmapWidth);
  pDict->SetAtInteger(FX_BSTRC("Height"), BitmapHeight);
  uint8_t* dest_buf = NULL;
  FX_STRSIZE dest_pitch = 0, dest_size = 0, opType = -1;
  if (bpp == 1) {
    int32_t reset_a = 0, reset_r = 0, reset_g = 0, reset_b = 0;
    int32_t set_a = 0, set_r = 0, set_g = 0, set_b = 0;
    if (!pBitmap->IsAlphaMask()) {
      ArgbDecode(pBitmap->GetPaletteArgb(0), reset_a, reset_r, reset_g,
                 reset_b);
      ArgbDecode(pBitmap->GetPaletteArgb(1), set_a, set_r, set_g, set_b);
    }
    if (set_a == 0 || reset_a == 0) {
      pDict->SetAt(FX_BSTRC("ImageMask"), new CPDF_Boolean(TRUE));
      if (reset_a == 0) {
        CPDF_Array* pArray = new CPDF_Array;
        pArray->AddInteger(1);
        pArray->AddInteger(0);
        pDict->SetAt(FX_BSTRC("Decode"), pArray);
      }
    } else {
      CPDF_Array* pCS = new CPDF_Array;
      pCS->AddName(FX_BSTRC("Indexed"));
      pCS->AddName(FX_BSTRC("DeviceRGB"));
      pCS->AddInteger(1);
      CFX_ByteString ct;
      FX_CHAR* pBuf = ct.GetBuffer(6);
      pBuf[0] = (FX_CHAR)reset_r;
      pBuf[1] = (FX_CHAR)reset_g;
      pBuf[2] = (FX_CHAR)reset_b;
      pBuf[3] = (FX_CHAR)set_r;
      pBuf[4] = (FX_CHAR)set_g;
      pBuf[5] = (FX_CHAR)set_b;
      ct.ReleaseBuffer(6);
      pCS->Add(CPDF_String::Create(ct, TRUE));
      pDict->SetAt(FX_BSTRC("ColorSpace"), pCS);
    }
    pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 1);
    dest_pitch = (BitmapWidth + 7) / 8;
    if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) {
      opType = 1;
    } else {
      opType = 0;
    }
  } else if (bpp == 8) {
    int32_t iPalette = pBitmap->GetPaletteSize();
    if (iPalette > 0) {
      CPDF_Array* pCS = new CPDF_Array;
      m_pDocument->AddIndirectObject(pCS);
      pCS->AddName(FX_BSTRC("Indexed"));
      pCS->AddName(FX_BSTRC("DeviceRGB"));
      pCS->AddInteger(iPalette - 1);
      uint8_t* pColorTable = FX_Alloc2D(uint8_t, iPalette, 3);
      uint8_t* ptr = pColorTable;
      for (int32_t i = 0; i < iPalette; i++) {
        FX_DWORD argb = pBitmap->GetPaletteArgb(i);
        ptr[0] = (uint8_t)(argb >> 16);
        ptr[1] = (uint8_t)(argb >> 8);
        ptr[2] = (uint8_t)argb;
        ptr += 3;
      }
      CPDF_Stream* pCTS = CPDF_Stream::Create(pColorTable, iPalette * 3,
                                              CPDF_Dictionary::Create());
      m_pDocument->AddIndirectObject(pCTS);
      pCS->AddReference(m_pDocument, pCTS);
      pDict->SetAtReference(FX_BSTRC("ColorSpace"), m_pDocument, pCS);
    } else {
      pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray"));
    }
    pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8);
    if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) {
      dest_pitch = BitmapWidth;
      opType = 1;
    } else {
      opType = 0;
    }
  } else {
    pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceRGB"));
    pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8);
    if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) {
      dest_pitch = BitmapWidth * 3;
      opType = 2;
    } else {
      opType = 0;
    }
  }
  const CFX_DIBitmap* pMaskBitmap = NULL;
  FX_BOOL bDeleteMask = FALSE;
  if (pBitmap->HasAlpha()) {
    pMaskBitmap = pBitmap->GetAlphaMask();
    bDeleteMask = TRUE;
  }
  if (!pMaskBitmap && pMask) {
    FXDIB_Format maskFormat = pMask->GetFormat();
    if (maskFormat == FXDIB_1bppMask || maskFormat == FXDIB_8bppMask) {
      pMaskBitmap = pMask;
    }
  }
  if (pMaskBitmap) {
    int32_t maskWidth = pMaskBitmap->GetWidth();
    int32_t maskHeight = pMaskBitmap->GetHeight();
    uint8_t* mask_buf = NULL;
    FX_STRSIZE mask_size = 0;
    CPDF_Dictionary* pMaskDict = new CPDF_Dictionary;
    pMaskDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject"));
    pMaskDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image"));
    pMaskDict->SetAtInteger(FX_BSTRC("Width"), maskWidth);
    pMaskDict->SetAtInteger(FX_BSTRC("Height"), maskHeight);
    pMaskDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray"));
    pMaskDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8);
    if (pMaskBitmap->GetBPP() == 8 &&
        (iCompress & PDF_IMAGE_MASK_LOSSY_COMPRESS) != 0) {
      _DCTEncodeBitmap(pMaskDict, pMaskBitmap, pParam ? pParam->nQuality : 75,
                       mask_buf, mask_size);
    } else if (pMaskBitmap->GetFormat() == FXDIB_1bppMask) {
      _JBIG2EncodeBitmap(pMaskDict, pMaskBitmap, m_pDocument, mask_buf,
                         mask_size, TRUE);
    } else {
      mask_buf = FX_Alloc2D(uint8_t, maskHeight, maskWidth);
      mask_size = maskHeight * maskWidth;  // Safe since checked alloc returned.
      for (int32_t a = 0; a < maskHeight; a++) {
        FXSYS_memcpy(mask_buf + a * maskWidth, pMaskBitmap->GetScanline(a),
                     maskWidth);
      }
    }
    pMaskDict->SetAtInteger(FX_BSTRC("Length"), mask_size);
    if (bUseMatte) {
      int a, r, g, b;
      ArgbDecode(*(pParam->pMatteColor), a, r, g, b);
      CPDF_Array* pMatte = new CPDF_Array;
      pMatte->AddInteger(r);
      pMatte->AddInteger(g);
      pMatte->AddInteger(b);
      pMaskDict->SetAt(FX_BSTRC("Matte"), pMatte);
    }
    CPDF_Stream* pMaskStream = new CPDF_Stream(mask_buf, mask_size, pMaskDict);
    m_pDocument->AddIndirectObject(pMaskStream);
    pDict->SetAtReference(FX_BSTRC("SMask"), m_pDocument, pMaskStream);
    if (bDeleteMask) {
      delete pMaskBitmap;
    }
  }
  FX_BOOL bStream = pFileWrite != NULL && pFileRead != NULL;
  if (opType == 0) {
    if (iCompress & PDF_IMAGE_LOSSLESS_COMPRESS) {
      if (pBitmap->GetBPP() == 1) {
        _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size,
                           TRUE);
      }
    } else {
      if (pBitmap->GetBPP() == 1) {
        _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size,
                           FALSE);
      } else if (pBitmap->GetBPP() >= 8 && pBitmap->GetPalette() != NULL) {
        CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap();
        pNewBitmap->Copy(pBitmap);
        pNewBitmap->ConvertFormat(FXDIB_Rgb);
        SetImage(pNewBitmap, iCompress, pFileWrite, pFileRead);
        if (pDict) {
          pDict->Release();
          pDict = NULL;
        }
        FX_Free(dest_buf);
        dest_buf = NULL;
        dest_size = 0;
        delete pNewBitmap;
        return;
      } else {
        if (bUseMatte) {
          CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap();
          pNewBitmap->Create(BitmapWidth, BitmapHeight, FXDIB_Argb);
          uint8_t* dst_buf = pNewBitmap->GetBuffer();
          int32_t src_offset = 0;
          for (int32_t row = 0; row < BitmapHeight; row++) {
            src_offset = row * src_pitch;
            for (int32_t column = 0; column < BitmapWidth; column++) {
              FX_FLOAT alpha = src_buf[src_offset + 3] / 255.0f;
              dst_buf[src_offset] = (uint8_t)(src_buf[src_offset] * alpha);
              dst_buf[src_offset + 1] =
                  (uint8_t)(src_buf[src_offset + 1] * alpha);
              dst_buf[src_offset + 2] =
                  (uint8_t)(src_buf[src_offset + 2] * alpha);
              dst_buf[src_offset + 3] = (uint8_t)(src_buf[src_offset + 3]);
              src_offset += 4;
            }
          }
          _DCTEncodeBitmap(pDict, pNewBitmap, pParam ? pParam->nQuality : 75,
                           dest_buf, dest_size);
          delete pNewBitmap;
        } else {
          _DCTEncodeBitmap(pDict, pBitmap, pParam ? pParam->nQuality : 75,
                           dest_buf, dest_size);
        }
      }
    }
    if (bStream) {
      pFileWrite->WriteBlock(dest_buf, dest_size);
      FX_Free(dest_buf);
      dest_buf = NULL;
    }
  } else if (opType == 1) {
    if (!bStream) {
      dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight);
      dest_size =
          dest_pitch * BitmapHeight;  // Safe since checked alloc returned.
    }
    uint8_t* pDest = dest_buf;
    for (int32_t i = 0; i < BitmapHeight; i++) {
      if (!bStream) {
        FXSYS_memcpy(pDest, src_buf, dest_pitch);
        pDest += dest_pitch;
      } else {
        pFileWrite->WriteBlock(src_buf, dest_pitch);
      }
      src_buf += src_pitch;
    }
  } else if (opType == 2) {
    if (!bStream) {
      dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight);
      dest_size =
          dest_pitch * BitmapHeight;  // Safe since checked alloc returned.
    } else {
      dest_buf = FX_Alloc(uint8_t, dest_pitch);
    }
    uint8_t* pDest = dest_buf;
    int32_t src_offset = 0;
    int32_t dest_offset = 0;
    for (int32_t row = 0; row < BitmapHeight; row++) {
      src_offset = row * src_pitch;
      for (int32_t column = 0; column < BitmapWidth; column++) {
        FX_FLOAT alpha = bUseMatte ? src_buf[src_offset + 3] / 255.0f : 1;
        pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha);
        pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha);
        pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha);
        dest_offset += 3;
        src_offset += bpp == 24 ? 3 : 4;
      }
      if (bStream) {
        pFileWrite->WriteBlock(pDest, dest_pitch);
        pDest = dest_buf;
      } else {
        pDest += dest_pitch;
      }
      dest_offset = 0;
    }
    if (bStream) {
      FX_Free(dest_buf);
      dest_buf = NULL;
    }
  }
  if (m_pStream == NULL) {
    m_pStream = new CPDF_Stream(NULL, 0, NULL);
  }
  if (!bStream) {
    m_pStream->InitStream(dest_buf, dest_size, pDict);
  } else {
    pFileWrite->Flush();
    m_pStream->InitStream(pFileRead, pDict);
  }
  m_bIsMask = pBitmap->IsAlphaMask();
  m_Width = BitmapWidth;
  m_Height = BitmapHeight;
  FX_Free(dest_buf);
}
void CPDF_Image::ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pBitmap) {
  pPage->GetRenderCache()->ResetBitmap(m_pStream, pBitmap);
}
