/*乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//
    bolpls.cpp
//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗*/

#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;

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

#include <bolalg.h>
#include <bolbas.h>
#include <bolfro.h>
#include "bolpls.h"

#define  MODNAM  "BOLPLS"
#define  MODVER  OCTVAL(2,6,0,0)

#ifdef __cplusplus
extern "C" {
#endif

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

  // 弶婜壔僷儔儊乕僞
static GdiplusStartupInput gdiSI;
static ULONG_PTR gdiTkn;

  // 僄儞僐乕僟忣曬
static WCHAR *mim[] = { L"image/bmp", L"image/jpeg", L"image/tiff", L"image/gif", L"image/png" };
static CLSID cid[_countof(mim)];

BOOL LOCALF gdiplus_startup(void)
{ // 弶婜壔
  U4B i, j, ni = 0, sz = 0;
  ImageCodecInfo *pICI;

  if (GdiplusStartup(&gdiTkn, &gdiSI, NULL) != Ok) { return (BOOL)ierr(E_DLL);}
  GetImageEncodersSize(&ni, &sz); if (sz == 0) { return (BOOL)ierr(E_DAT);}
  pICI = (ImageCodecInfo *)malloc(sz); if (!pICI) { return (BOOL)ierr(E_MEM);}
  GetImageEncoders(ni, sz, pICI);
  for (i = 0; i < _countof(mim); i++) {
    for (j = 0; j < ni; j++) {
      if (!wcscmp(pICI[j].MimeType, mim[i])) {
        cid[i] = pICI[j].Clsid; break;
      }
    }
  }
  free(pICI);
  return TRUE;
}

#define  GFF_BMP  0
#define  GFF_JPG  1
#define  GFF_TIF  2
#define  GFF_GIF  3
#define  GFF_PNG  4

I4B  LOCALF file_format(rSTR nam)
{ // 僼傽僀儖柤偺奼挘巕偱夋憸僼僅乕儅僢僩傪敾暿
  I4B i;
  static CODI ff[] = {
    { GFF_BMP, ".bmp" }, { GFF_BMP, ".dib" }, { GFF_JPG, ".jpg" }, { GFF_JPG, ".jpeg"},
    { GFF_JPG, ".jpe" }, { GFF_JPG, ".jfif"}, { GFF_TIF, ".tif" }, { GFF_TIF, ".tiff"},
    { GFF_GIF, ".gif" }, { GFF_PNG, ".png" },
  };

  for (i = 0; i < _countof(ff); i++) {
    if (strirfind(nam, ff[i].st)) { return ff[i].va;}
  }
  return GFF_BMP;
}

#define  Encoder(i)  (&cid[i])

HIMG WINAPI LoadIMG(HIMG im, rSTR nam)
{ // 夋憸僼傽僀儖撉崬
  I4B i, j, w, h;
  HIMG ix;
  WCHAR wnm[LBUF];

  MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, nam, -1, wnm, _countof(wnm));
  Bitmap img(wnm);
  w = img.GetWidth();
  h = img.GetHeight();
  ix = CreateIMG(w, h, 0); if (!ix) return NULL;
  for (i = 0; i < h; i++) {
    for (j = 0; j < w; j++) {
      img.GetPixel(j, i, (Color *)&ix->bi[i * w + j]);
    }
  }
  return im? MoveIMG(im, ix): ix;
}

  // 僄儞僐乕僪昳幙(%)
static I4B  QualityValue = 95;

BOOL WINAPI SaveIMG(HIMG im, rSTR nam)
{ // 夋憸僼傽僀儖彂弌
  I4B i, j, w, h;
  CLSID *pc;
  WCHAR wnm[LBUF];

  MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, nam, -1, wnm, _countof(wnm));
  pc = Encoder(file_format(nam));
  w = im->w;
  h = im->h;
  Bitmap img(w, h, PixelFormat32bppARGB);
  for (i = 0; i < h; i++) {
    for (j = 0; j < w; j++) {
      img.SetPixel(j, i, *(Color *)&im->bi[i * w + j]);
    }
  }
  EncoderParameters ep;
  ep.Count = 1;
  ep.Parameter[0].Guid = EncoderQuality;
  ep.Parameter[0].Type = EncoderParameterValueTypeLong;
  ep.Parameter[0].NumberOfValues = 1;
  ep.Parameter[0].Value = &QualityValue;
  return img.Save(wnm, pc, &ep) == Ok;
}

HDIB WINAPI LoadJPG(HDIB bm, rSTR nam)
{ // 夋憸僼傽僀儖撉崬
  HIMG im;
  HDIB bx;

  if (file_format(nam) == GFF_BMP) { return LoadBMP(bm, nam);}
  im = LoadIMG(NULL, nam); if (!im) return NULL;
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return NULL;
  return bm? MoveDIB(bm, bx): bx;
}

BOOL WINAPI SaveJPG(HDIB bm, rSTR nam)
{ // 夋憸僼傽僀儖彂弌
  I4B re;
  HIMG im;

  if (file_format(nam) == GFF_BMP) { return SaveBMP(bm, nam);}
  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  re = SaveIMG(im, nam); DeleteIMG(im);
  return re;
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

U4B  WINAPI BOLPLSVer(void)
{ // 僶乕僕儑儞忣曬
  return MODVER;
}

BOOL WINAPI InitBOLPLS(uANY pa)
{ // 奐巒張棟
  return gdiplus_startup();
}

void WINAPI TermBOLPLS(void)
{ // 廔椆張棟
  GdiplusShutdown(gdiTkn);
}

#ifdef __cplusplus
}
#endif

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//
