SOL9 2.0 Class: ImageBlender

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree  SOL9 ClassList 

Source code

/******************************************************************************
 *
 * Copyright (c) 2012 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *  ImageBlender.h
 *
 *****************************************************************************/

// SOL9
// 2012/04/22
// 2012/05/31 Updated
// 2012/06/16 Updated

#pragma once

#include <sol/Object.h>
#include <sol/File.h>
#include <sol/WString.h>
#include <sol/gdiplus/ImageTransformer.h>
#include <sol/gdiplus/ImageFilters.h>
#include <sol/gdiplus/ImageFileFilter.h>

#include <sol/LinkedList.h>

namespace SOL {

class ImageBlender :public ImageTransformer {

public:
  ImageBlender()
  {
  }

public:
  ~ImageBlender()
  {
  }

public:
  //
  bool blend(const wchar_t* sourceFileName, const wchar_t* backImageFileName, const wchar_t* saveFileName, const wchar_t* name)
  {
    bool rc = false;
    if (sourceFileName == NULL || backImageFileName == NULL || saveFileName == NULL) {
      throw Exception (0, "Exception: FileName is NULL.");
    }

    Gdiplus::Bitmap* blendedBitmap = blendImage(sourceFileName, backImageFileName, name);
    if (blendedBitmap) {
      try {
        rc = saveAs(blendedBitmap, saveFileName);
      } catch (...) {

      }
      delete blendedBitmap;
    }
    return rc;    
  }

public:
  /*
  */
  bool blend(const TCHAR* backColorName, LinkedList& imageFileList, const TCHAR* saveFileName)
  {
    bool rc = false;
    Gdiplus::Bitmap* blendedBitmap = blendImage(backColorName, imageFileList);
    if (blendedBitmap){
      rc = saveAs(blendedBitmap, _bstr_t(saveFileName));

      delete blendedBitmap;
    }
    return rc;
  }

public:
  // name takes 'alpha:scale' where scale is a float type alpha blending scale parameter.
  //2012/05/31
  Gdiplus::Bitmap* blendImage(const wchar_t* sourceFileName, const wchar_t* backImageFileName, const wchar_t* name)
  {
    if (sourceFileName == NULL || backImageFileName == NULL) {
      throw Exception (0, "Exception: FileName is NULL.");
    }

    Gdiplus::Bitmap* blendedBitmap = NULL;

    Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(sourceFileName, TRUE);

    if (bitmap && bitmap-> GetLastStatus() == Gdiplus::Ok) {
      UINT w = bitmap->GetWidth();
      UINT h = bitmap->GetHeight();
      wprintf(L"SourceImageSize: width=%d height=%d  %s\n",
          w, h, sourceFileName);

      Gdiplus::Bitmap* backBitmap = new Gdiplus::Bitmap(backImageFileName, TRUE);
      if (backBitmap && backBitmap-> GetLastStatus() == Gdiplus::Ok) {

        ImageFilters filters;
        Gdiplus::ColorMatrix matrix;
        if (filters.getColorMatrix(name, matrix)) {

          blendedBitmap = createBlendedBitmap(bitmap, backBitmap, matrix);

          if (blendedBitmap && blendedBitmap-> GetLastStatus() != Gdiplus::Ok) {
            delete blendedBitmap;
            blendedBitmap = NULL;
          }
        }
        delete backBitmap;
      }
      delete bitmap;
    }
    return blendedBitmap;
  }

public:
  // name takes 'alpha:scale' where scale is a float type alpha blending scale parameter.
  //2012/05/31
  Gdiplus::Bitmap* blendImage(const wchar_t* sourceFileName, Gdiplus::Bitmap* backBitmap, const wchar_t* name)
  {
    if (sourceFileName == NULL ) {
      throw Exception (0, "Exception: FileName is NULL.");
    }

    Gdiplus::Bitmap* blendedBitmap = NULL;

    Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(sourceFileName, TRUE);

    if (bitmap && bitmap-> GetLastStatus() == Gdiplus::Ok) {
      UINT w = bitmap->GetWidth();
      UINT h = bitmap->GetHeight();
      wprintf(L"SourceImageSize: width=%d height=%d  %s\n",
          w, h, sourceFileName);

      if (backBitmap && backBitmap-> GetLastStatus() == Gdiplus::Ok) {

        ImageFilters filters;
        Gdiplus::ColorMatrix matrix;
        if (filters.getColorMatrix(name, matrix)) {

          blendedBitmap = createBlendedBitmap(bitmap, backBitmap, matrix);

          if (blendedBitmap && blendedBitmap-> GetLastStatus() != Gdiplus::Ok) {
            delete blendedBitmap;
            blendedBitmap = NULL;
          }
        }
        //delete backBitmap;
      }
      delete bitmap;
    }
    return blendedBitmap;
  }

public:
  Gdiplus::Bitmap* createBlendedBitmap(Gdiplus::Bitmap* sourceBitmap,
    Gdiplus::Bitmap* backBitmap, Gdiplus::ColorMatrix& matrix)
  {
    int width  = sourceBitmap->GetWidth();
    int height = sourceBitmap->GetHeight();

    int bwidth  = backBitmap->GetWidth();
    int bheight = backBitmap->GetHeight();

    Gdiplus::Graphics* desktopGraphics = Gdiplus::Graphics::FromHWND(NULL);

    Gdiplus::Bitmap* destBitmap = new Gdiplus::Bitmap(width, height, desktopGraphics);

    Gdiplus::Graphics* destGraphics = new Gdiplus::Graphics(destBitmap);

    //1 Draw the bacBitmap 
    destGraphics->DrawImage(backBitmap, 0, 0, bwidth, bheight);

    Gdiplus::ImageAttributes imageAttributes;
    imageAttributes.SetColorMatrix(&matrix,
        Gdiplus::ColorMatrixFlagsDefault, 
                        Gdiplus::ColorAdjustTypeBitmap);
    //2 Draw the sourceBitmap with a imageAttribute onto the backBitmap 
    destGraphics->DrawImage(sourceBitmap, 
      Gdiplus::RectF((Gdiplus::REAL)0, (Gdiplus::REAL)0, (Gdiplus::REAL)width, (Gdiplus::REAL)height),
      (Gdiplus::REAL)0, (Gdiplus::REAL)0, (Gdiplus::REAL)width, (Gdiplus::REAL)height, 
      Gdiplus::UnitPixel,
      &imageAttributes);
    
    delete desktopGraphics;    
    delete destGraphics;

    return destBitmap;
  }

public:
  //
  bool blend(const wchar_t* sourceFileName, COLORREF backColor, 
    const wchar_t* saveFileName, const wchar_t* name)
  {
    bool rc = false;
    if (sourceFileName == NULL || saveFileName == NULL) {
      throw Exception (0, "Exception: FileName is NULL.");
    }
    
    Gdiplus::Bitmap* blendedBitmap = blendImage(sourceFileName, backColor, name);
    if (blendedBitmap) {
      try {
        rc = saveAs(blendedBitmap, saveFileName);
      } catch (...) {
        
      }
      delete blendedBitmap;
    }
    return rc;    
  }

public:
  /*
  */
  //2012/06/16 Updated
  Gdiplus::Bitmap* blendImage(const TCHAR* backColorName, LinkedList& imageFileList)
  {
    COLORREF backColor = 0;
    if (toColor(backColorName, backColor) != true) {
      throw Exception (0, _T("Exception: Invalid backColorName '%s'."), backColorName);
    }
    return blendImage(backColor, imageFileList);
    /*
    if (imageFileList.getLength() ==0) {
      throw Exception (0, _T("Exception: ImageFileFilter list is empty."));
    }

    ListEntry* entry = imageFileList.getEntry();
    // 1 Get maxwidth and maxHeight from imageFileList;

    int width = 0;
    int height= 0;    
    while (entry) {
      ImageFileFilter* imageFileFilter = (ImageFileFilter*)entry->getObject();
      const wchar_t* fileName = imageFileFilter->getFileName();
      int w, h;
      getImageSize(fileName, w, h);  
      if (w > width) {
        width = w;
      }
      if (h > height) {
        height = h;
      }
      entry = entry->getNext();
    }
    return blendImage(width, height, backColor, imageFileList);
    */
  }

public:
  /*
  */
  //2012/06/16 Updated
  Gdiplus::Bitmap* blendImage(COLORREF backColor,LinkedList& imageFileList)
  {
    /*
    COLORREF backColor = 0;
    if (toColor(backColorName, backColor) != true) {
      throw Exception (0, _T("Exception: Invalid backColorName '%s'."), backColorName);
    }
    */

    if (imageFileList.getLength() ==0) {
      throw Exception (0, _T("Exception: ImageFileFilter list is empty."));
    }

    ListEntry* entry = imageFileList.getEntry();
    // 1 Get maxwidth and maxHeight from imageFileList;

    int width = 0;
    int height= 0;    
    while (entry) {
      ImageFileFilter* imageFileFilter = (ImageFileFilter*)entry->getObject();
      const wchar_t* fileName = imageFileFilter->getFileName();
      int w, h;
      getImageSize(fileName, w, h);  
      if (w > width) {
        width = w;
      }
      if (h > height) {
        height = h;
      }
      entry = entry->getNext();
    }
    return blendImage(width, height, backColor, imageFileList);
  }

public:
  /*
  */
  //2012/06/16 Updated
  Gdiplus::Bitmap* blendImage(unsigned int width, unsigned int height, 
    COLORREF backColor, LinkedList& imageFileList)
  {
    if (imageFileList.getLength() ==0) {
      return NULL;
    }
    
    Gdiplus::Graphics* desktopGraphics = Gdiplus::Graphics::FromHWND(NULL);

    Gdiplus::Bitmap* blendedBitmap = new Gdiplus::Bitmap(width, height, desktopGraphics);

    Gdiplus::Graphics* destGraphics = new Gdiplus::Graphics(blendedBitmap);

    Gdiplus::Color color;
    color.SetFromCOLORREF(backColor);
     Gdiplus::SolidBrush colorBrush(color);

    //1 Draw a rectangle with a colorBrush specified by backColor
    destGraphics->FillRectangle(&colorBrush, 0, 0, width, height);
  
    ListEntry* entry = imageFileList.getEntry();

    while (entry) {
      ImageFileFilter* imageFileFilter = (ImageFileFilter*)entry->getObject();
      const wchar_t* fileName = imageFileFilter->getFileName();
      const wchar_t* filerName = imageFileFilter->getFilterName();
      const wchar_t* alignment = imageFileFilter->getAlignment();
      const wchar_t* resize    = imageFileFilter->getSize();
      int percent = 100;
      WString string = resize;
      if (string.contains(L"%")) {
        WString spercent, any;
        if (string.split((wchar_t)'%', spercent, any)==1) {
          percent = atoi((const wchar_t*)spercent);
        }
      }
      Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(fileName, TRUE);
      if (bitmap) {
        if (bitmap->GetLastStatus() == Gdiplus::Ok) {
          int ww = bitmap->GetWidth();
          int hh = bitmap->GetHeight();
          int www = (ww * percent)/100;
          int hhh = (hh * percent)/100;

          ImageFilters filters;
          Gdiplus::ColorMatrix matrix;
          if (filters.getColorMatrix(filerName, matrix)) {
    
            Gdiplus::ImageAttributes imageAttributes;
    
            imageAttributes.SetColorMatrix(&matrix,
              Gdiplus::ColorMatrixFlagsDefault, 
              Gdiplus::ColorAdjustTypeBitmap);

              // 2 Draw the bitmap with an imageAttribute onto the blendedBitmap 
              //LeftTop
          
              int destX = 0;
              int destY = 0;

              if (_wcsicmp(alignment, L"Center") == 0) {
                 destX = (width-www)/2;
                 destY = (height-hhh)/2;
               }
               if (_wcsicmp(alignment, L"LeftTop") == 0) {
                 destX = 0;
                 destY = 0;
               }
               if (_wcsicmp(alignment, L"LeftBottom") ==0) {
                 destX = 0;
                 destY = (height-hhh);
               }
               if (_wcsicmp(alignment, L"RightTop") ==0) {
                 destX = (width-www);
                 destY = 0;
               }
               if (_wcsicmp(alignment, L"RightBottom") == 0) {
                 destX = (width-www);
                 destY = (height-hhh);
               }
               destGraphics->DrawImage(bitmap, 
                  Gdiplus::Rect(destX, destY, www, hhh),
                  0, 0, ww, hh,
                  Gdiplus::UnitPixel,
                  &imageAttributes);
          }
        }
        delete bitmap;
      }
      entry = entry->getNext();
    }

    return blendedBitmap;
  }

public:
  //2012/05/31
  Gdiplus::Bitmap* blendImage(const wchar_t* sourceFileName, COLORREF backColor, 
    const wchar_t* name)
  {
    if (sourceFileName == NULL) {
      throw Exception (0, "Exception: FileName is NULL.");
    }

    Gdiplus::Bitmap* blendedBitmap = NULL;

    Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(sourceFileName, TRUE);

    if (bitmap && bitmap-> GetLastStatus() == Gdiplus::Ok) {
      UINT w = bitmap->GetWidth();
      UINT h = bitmap->GetHeight();
      wprintf(L"SourceImageSize: width=%d height=%d  %s\n",
          w, h, sourceFileName);

      ImageFilters filters;
      Gdiplus::ColorMatrix matrix;
      if (filters.getColorMatrix(name, matrix)) {

        blendedBitmap = createBlendedBitmap(bitmap, backColor, matrix);

        if (blendedBitmap && blendedBitmap-> GetLastStatus() != Gdiplus::Ok) {
          delete blendedBitmap;
          blendedBitmap = NULL;
        }
      }
      delete bitmap;
    }
    return blendedBitmap;    
  }

public:
  //2012/06/-3
  Gdiplus::Bitmap* blendImage(Gdiplus::Bitmap* bitmap, COLORREF backColor, const wchar_t* name)
  {

    Gdiplus::Bitmap* blendedBitmap = NULL;

    if (bitmap && bitmap-> GetLastStatus() == Gdiplus::Ok) {

      ImageFilters filters;
      Gdiplus::ColorMatrix matrix;
      if (filters.getColorMatrix(name, matrix)) {

        blendedBitmap = createBlendedBitmap(bitmap, backColor, matrix);

        if (blendedBitmap && blendedBitmap-> GetLastStatus() != Gdiplus::Ok) {
          delete blendedBitmap;
          blendedBitmap = NULL;
        }
      }
    }
    return blendedBitmap;    
  }

public:
  Gdiplus::Bitmap* createBlendedBitmap(Gdiplus::Bitmap* sourceBitmap, COLORREF backColor, Gdiplus::ColorMatrix& matrix)
  {
    int width  = sourceBitmap->GetWidth();
    int height = sourceBitmap->GetHeight();

    Gdiplus::Graphics* desktopGraphics = Gdiplus::Graphics::FromHWND(NULL);

    Gdiplus::Bitmap* destBitmap = new Gdiplus::Bitmap(width, height, desktopGraphics);

    Gdiplus::Graphics* destGraphics = new Gdiplus::Graphics(destBitmap);

    Gdiplus::Color color;
    color.SetFromCOLORREF(backColor);
     Gdiplus::SolidBrush colorBrush(color);

    //1 Draw a rectangle with a colorBrush specified by backColor
    destGraphics->FillRectangle(&colorBrush, 0, 0, width, height);

    Gdiplus::ImageAttributes imageAttributes;
    imageAttributes.SetColorMatrix(&matrix,
        Gdiplus::ColorMatrixFlagsDefault, 
                        Gdiplus::ColorAdjustTypeBitmap);
    //2 Draw the sourceBitmap with a imageAttribute onto the rectabgke with a background color specified by backColorn 
    destGraphics->DrawImage(sourceBitmap, 
      Gdiplus::RectF((Gdiplus::REAL)0, (Gdiplus::REAL)0, (Gdiplus::REAL)width, (Gdiplus::REAL)height),
      (Gdiplus::REAL)0, (Gdiplus::REAL)0, (Gdiplus::REAL)width, (Gdiplus::REAL)height, 
      Gdiplus::UnitPixel,
      &imageAttributes);
    
    delete desktopGraphics;    
    delete destGraphics;

    return destBitmap;
  }

public:
  //
  // @color: takes the format "#RRGGBB";
  //
  bool toColor(__in const TCHAR* color, __out COLORREF& rgb)
  {
    bool rc = false;
    rgb = 0;
    if (color && *color == '#') {
      color++;
      if (strlen(color) == 6) {
        TCHAR r[3], g[3], b[3];
        memcpy(r, color, 2);
        r[2] = NULL;
        color +=2;

        memcpy(g, color, 2);
        g[2] = NULL;
        color +=2;
        memcpy(b, color, 2);
        b[2] = NULL;
      
        unsigned int rvalue = _tcstoul(r, NULL, 16);    
        unsigned int gvalue = _tcstoul(g, NULL, 16);
        unsigned int bvalue = _tcstoul(b, NULL, 16);

        rgb = RGB(rvalue,gvalue,bvalue);
        rc = true;
      }
    }
    return rc;
  }

};

}

Last modified: 5 May 2019

Copyright (c) 2009-2019 Antillia.com ALL RIGHTS RESERVED.