Frost Moon Project

Src/MainDialog.cpp -MagicPNG Ver.1.00- - Frost Moon Project   アクセスランキング  

Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > MainDialog.cpp

 
//MainDialog.cpp
//メインダイアログ

//`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`
//          MagicPNG Ver.1.00 by x@rgs
//          Released under NYSL Version 0.9982
//
//`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`~^`


#include"StdAfx.h"
#include"MainDialog.h"
#include<math.h>

using namespace sslib;



namespace{
//イメージファイルからリサイズしてHBITMAPを取得
HBITMAP getThumbnailFromImage(LPCTSTR file_path,int thumbnail_width,int thumbnail_height){
    Gdiplus::Bitmap* bitmap=Gdiplus::Bitmap::FromFile(file_path);
    if(bitmap->GetLastStatus()!=Gdiplus::Ok)return NULL;

    HBITMAP hbitmap=NULL;
    bitmap->GetHBITMAP(0,&hbitmap);

    //リサイズしない場合
    if(!thumbnail_width&&!thumbnail_height){
        SAFE_DELETE(bitmap);
        return hbitmap;
    }

    int dest_width=0;
    int dest_height=0;
    int src_width=bitmap->GetWidth();
    int src_height=bitmap->GetHeight();

    SAFE_DELETE(bitmap);

    if(thumbnail_width){
        //幅基準で作成
        if(thumbnail_width<src_width){
            float x=(float)thumbnail_width/src_width;
            float y=(float)thumbnail_width/src_height;
            //縮小後のサイズ
            dest_width=(int)(min(x,y)*src_width);
            dest_height=(int)(min(x,y)*src_height);

        }else{
            //幅か高さのどちらかが指定サイズ以下ならリサイズしない
            return hbitmap;
        }
    }else{
        //高さ基準で作成
        if(thumbnail_height<src_height){
            float x=(float)thumbnail_height/src_width;
            float y=(float)thumbnail_height/src_height;
            //縮小後のサイズ
            dest_width=(int)(min(x,y)*src_width);
            dest_height=(int)(min(x,y)*src_height);
        }else{
            //幅か高さのどちらかが指定サイズ以下ならリサイズしない
            return hbitmap;
        }
    }

    HDC hdc_screen=::GetDC(NULL);

    HDC hdc_tmp=::CreateCompatibleDC(hdc_screen);
    ::SelectObject(hdc_tmp,hbitmap);

    HDC hdc_memory=::CreateCompatibleDC(hdc_screen);
    HBITMAP hbitmap_result=::CreateCompatibleBitmap(hdc_screen,dest_width,dest_height);
    HGDIOBJ hobj_old=::SelectObject(hdc_memory,hbitmap_result);

    ::SetStretchBltMode(hdc_memory,HALFTONE);
    HPALETTE hpalette=::CreateHalftonePalette(hdc_memory);
    HPALETTE hpalette_old=::SelectPalette(hdc_memory,hpalette,false);
    ::RealizePalette(hdc_memory);

    ::StretchBlt(hdc_memory,0,0,dest_width,dest_height,hdc_tmp,0,0,src_width,src_height,SRCCOPY);

    ::SelectPalette(hdc_memory,hpalette_old,false);
    ::DeleteObject(hpalette);
    ::ReleaseDC(NULL,hdc_screen);

    ::SelectObject(hdc_memory,hobj_old);
    ::DeleteDC(hdc_tmp);
    ::DeleteObject(hbitmap);

    return hbitmap_result;
}

//サムネイルを設定
void setButtonThumbnail(HWND hButton,LPCTSTR image_path,int width,int height){
    HBITMAP hbitmap=NULL;

    if((hbitmap=getThumbnailFromImage(image_path,width,height))!=NULL){
        SendMessage(hButton,BM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)hbitmap);
    }
}

struct Options{
    double gamma;
    unsigned fade1;
    unsigned int fade2;
    unsigned int shift;
    //fadeについては後で/255.0すること
    Options():gamma(0.023),fade1(220),fade2(210),shift(10){}
};

Options options;
const Options default_options;

BYTE trans1(BYTE num){
    return BYTE(floor((pow((num*(options.fade1/255.0)+options.shift)/255.0,options.gamma))*255.0));
}

BYTE trans2(BYTE num){
    double r=num*(options.fade2/255.0);
    return BYTE((r>0.0)?floor(r+0.5):ceil(r-0.5));
}

int getEncoderCLSID(const TCHAR* format,CLSID* clsid){
    unsigned int num_encoders=0,size=0;

    Gdiplus::GetImageEncodersSize(&num_encoders,&size);
    if(size==0)return -1;

    Gdiplus::ImageCodecInfo* pImageCodecInfo=new Gdiplus::ImageCodecInfo[size];
    if(pImageCodecInfo==NULL)return -1;

    Gdiplus::GetImageEncoders(num_encoders,size,pImageCodecInfo);

    for(unsigned int index=0;index<num_encoders;++index){
        if(lstrcmp(pImageCodecInfo[index].MimeType,format)==0){
            *clsid=pImageCodecInfo[index].Clsid;
            SAFE_DELETE(pImageCodecInfo);
            return index;
        }
    }

    SAFE_DELETE(pImageCodecInfo);
    return -1;
}

}

INT_PTR MainDialog::DropButton::onDropFiles(HDROP drop_handle){
    DropFiles drop_files(drop_handle);

    RECT rc;

    ::GetWindowRect(handle(),&rc);
    setButtonThumbnail(handle(),drop_files.getFile(0).c_str(),rc.right-rc.left,0);
    ::SetWindowText(handle(),drop_files.getFile(0).c_str());
    return true;
}

INT_PTR MainDialog::onInitDialog(WPARAM wparam,LPARAM lparam){
    //アイコンの設定(タイトルバー)
    setIcon(IDI_ICON1);

    //タイトルの設定(タイトルバー)
    ::SetWindowText(handle(),(tstring(_T("MagicPNG Ver."))+SOFTWARE_VERSION).c_str());

    //サブクラス化してドロップでファイルを受け取る
    m_src1_button=new DropButton(handle(),IDC_BUTTON_SRC1);
    m_src2_button=new DropButton(handle(),IDC_BUTTON_SRC2);
    if(m_src1_button==NULL||m_src2_button==NULL){
        SAFE_DELETE(m_src1_button);
        SAFE_DELETE(m_src2_button);
        return false;
    }

    {
        //引数解析
        std::vector<tstring>& filepaths=static_cast<CommandArgument*>(param())->filepaths();

        for(std::vector<tstring>::size_type i=0,size=filepaths.size();i<size;++i){
            DropButton* ptr=(i==0)?m_src1_button:(i==1)?m_src2_button:NULL;
            RECT rc;

            if(ptr==NULL)break;
            ::GetWindowRect(ptr->handle(),&rc);
            setButtonThumbnail(ptr->handle(),filepaths[i].c_str(),rc.right-rc.left,0);
            ::SetWindowText(ptr->handle(),filepaths[i].c_str());
        }
    }

    //デフォルト設定に
    sendMessage(WM_COMMAND,MAKEWPARAM(IDC_BUTTON_DEFAULT,0),0);

    return true;
}

INT_PTR MainDialog::onCommand(WPARAM wparam,LPARAM lparam){
    switch(LOWORD(wparam)){
        case IDC_BUTTON_SRC1:
        case IDC_BUTTON_SRC2:{
            FileDialog file_dialog;
            tstring file_path;

            if(!file_dialog.doModalOpen(&file_path,
                                        handle(),
                                        _T("全てのファイル (*.*)\0*.*\0\0"),
                                        _T("処理したいファイルを選択してください"))){
                            return false;
            }
            RECT rc;

            ::GetWindowRect(getDlgItem(LOWORD(wparam)),&rc);
            setButtonThumbnail(getDlgItem(LOWORD(wparam)),file_path.c_str(),rc.right-rc.left,0);
            ::SetWindowText(getDlgItem(LOWORD(wparam)),file_path.c_str());
            break;
        }

        case IDC_BUTTON_DEFAULT:
            options=default_options;
            ::SetWindowText(getDlgItem(IDC_EDIT_GAMMA),format(_T("%f"),options.gamma).c_str());
            ::SetWindowText(getDlgItem(IDC_EDIT_FADE1),format(_T("%d"),options.fade1).c_str());
            ::SetWindowText(getDlgItem(IDC_EDIT_FADE2),format(_T("%d"),options.fade2).c_str());
            ::SetWindowText(getDlgItem(IDC_EDIT_SHIFT),format(_T("%d"),options.shift).c_str());
            break;

        case IDC_BUTTON_CREATE:{
            tstring src1_path,src2_path,output_path;
            std::vector<TCHAR> buffer(MAX_PATH);

            ::GetWindowText(getDlgItem(IDC_BUTTON_SRC1),&buffer[0],buffer.size());
            src1_path.assign(&buffer[0]);
            ::GetWindowText(getDlgItem(IDC_BUTTON_SRC2),&buffer[0],buffer.size());
            src2_path.assign(&buffer[0]);

            if(!path::fileExists(src1_path.c_str())||
               !path::fileExists(src2_path.c_str())){
                ::MessageBox(handle(),
                             _T("元画像を選択してください。"),
                             (tstring(_T("MagicPNG Ver."))+SOFTWARE_VERSION).c_str(),
                             MB_ICONEXCLAMATION);
                return false;
            }

            Gdiplus::Bitmap* src1_bitmap=Gdiplus::Bitmap::FromFile(src1_path.c_str(),TRUE);
            Gdiplus::Bitmap* src2_bitmap=Gdiplus::Bitmap::FromFile(src2_path.c_str(),TRUE);

            if(src1_bitmap==NULL||src2_bitmap==NULL){
                ::MessageBox(handle(),
                             _T("画像を開くことができません。"),
                             (tstring(_T("MagicPNG Ver."))+SOFTWARE_VERSION).c_str(),
                             MB_ICONEXCLAMATION);
                SAFE_DELETE(src1_bitmap);
                SAFE_DELETE(src2_bitmap);
                return false;
            }

            if(src1_bitmap->GetWidth()!=src2_bitmap->GetWidth()||
               src1_bitmap->GetHeight()!=src2_bitmap->GetHeight()){
                ::MessageBox(handle(),
                             _T("同じサイズの画像を選択してください。"),
                             (tstring(_T("MagicPNG Ver."))+SOFTWARE_VERSION).c_str(),
                             MB_ICONEXCLAMATION);
                SAFE_DELETE(src1_bitmap);
                SAFE_DELETE(src2_bitmap);
                return false;
            }
            SAFE_DELETE(src1_bitmap);
            SAFE_DELETE(src2_bitmap);

            FileDialog file_dialog;

            if(!file_dialog.doModalSave(&output_path,
                                        handle(),
                                        _T("PNGファイル (*.png)\0*.png\0\0"),
                                        _T("保存ファイル名を入力してください"),
                                        NULL,
                                        NULL,
                                        _T("png"))){
                            return false;
            }
            if(output_path.empty())return false;
            if(src1_path==output_path||
               src2_path==output_path||
               src1_path==src2_path)return false;

            //PNG作成
            createMagicPNG(output_path.c_str(),src1_path.c_str(),src2_path.c_str());
            break;
        }

        default:
            break;
    }

    switch(HIWORD(wparam)){
        case EN_CHANGE:
            std::vector<TCHAR> buffer(MAX_PATH);
            tstring buffer_str;

            switch(LOWORD(wparam)){
                case IDC_EDIT_GAMMA:
                case IDC_EDIT_FADE1:
                case IDC_EDIT_FADE2:
                case IDC_EDIT_SHIFT:
                    ::GetWindowText(getDlgItem(LOWORD(wparam)),&buffer[0],buffer.size());
                    buffer_str.assign(&buffer[0]);

                    if(!buffer_str.empty()){
                        switch(LOWORD(wparam)){
                            case IDC_EDIT_GAMMA:
                                options.gamma=_tstof(buffer_str.c_str());
                                break;
                            case IDC_EDIT_FADE1:
                                options.fade1=_tstoi(buffer_str.c_str());
                                break;
                            case IDC_EDIT_FADE2:
                                options.fade2=_tstoi(buffer_str.c_str());
                                break;
                            case IDC_EDIT_SHIFT:
                                options.shift=_tstoi(buffer_str.c_str());
                                break;
                            default:
                                break;
                        }
                    }
                    break;
            }
            break;
    }

    return false;
}

void MainDialog::createMagicPNG(const TCHAR* output_path,const TCHAR* src1_path,const TCHAR* src2_path){
    Gdiplus::Bitmap* src1_bitmap=Gdiplus::Bitmap::FromFile(src1_path,TRUE);
    Gdiplus::Bitmap* src2_bitmap=Gdiplus::Bitmap::FromFile(src2_path,TRUE);
    Gdiplus::Bitmap* output_bitmap=new Gdiplus::Bitmap(src1_bitmap->GetWidth()*2,src1_bitmap->GetHeight()*2,PixelFormat32bppARGB);

    if(src1_bitmap==NULL||src2_bitmap==NULL||output_bitmap==NULL){
        SAFE_DELETE(src1_bitmap);
        SAFE_DELETE(src2_bitmap);
        SAFE_DELETE(output_bitmap);
        return;
    }

    Gdiplus::BitmapData output_bitmap_data,src1_bitmap_data,src2_bitmap_data;

    output_bitmap->LockBits(NULL,Gdiplus::ImageLockModeWrite,PixelFormat32bppARGB,&output_bitmap_data);
    src1_bitmap->LockBits(NULL,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB,&src1_bitmap_data);
    src2_bitmap->LockBits(NULL,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB,&src2_bitmap_data);

    RGBQUAD* output_rgb=NULL;
    int bytes=output_bitmap_data.Stride;
    unsigned char* ptr=(unsigned char*)output_bitmap_data.Scan0;

    unsigned int width=output_bitmap->GetWidth();
    unsigned int height=output_bitmap->GetHeight();

    for(unsigned int y=0;y<height;y++){
        output_rgb=(RGBQUAD*)ptr;
        for(unsigned int x=0;x<width;x++){
            if(x%2==0&&y%2==0){
                RGBQUAD* src1_rgb=(RGBQUAD*)src1_bitmap_data.Scan0+x/2+(y/2*src1_bitmap_data.Stride/sizeof(RGBQUAD));

                output_rgb->rgbRed=trans1(src1_rgb->rgbRed);
                output_rgb->rgbGreen=trans1(src1_rgb->rgbGreen);
                output_rgb->rgbBlue=trans1(src1_rgb->rgbBlue);
                output_rgb->rgbReserved=src1_rgb->rgbReserved;
            }else{
                RGBQUAD* src2_rgb=(RGBQUAD*)src2_bitmap_data.Scan0+x/2+(y/2*src2_bitmap_data.Stride/sizeof(RGBQUAD));

                output_rgb->rgbRed=trans2(src2_rgb->rgbRed);
                output_rgb->rgbGreen=trans2(src2_rgb->rgbGreen);
                output_rgb->rgbBlue=trans2(src2_rgb->rgbBlue);
                output_rgb->rgbReserved=src2_rgb->rgbReserved;
            }
            output_rgb++;
        }
        if(y+1<height){
            ptr+=bytes;
        }
    }

    output_bitmap->UnlockBits(&output_bitmap_data);
    src1_bitmap->UnlockBits(&src1_bitmap_data);
    src2_bitmap->UnlockBits(&src2_bitmap_data);

    //gAMA(PropertyTagGamma)の値を変更
    unsigned long rational[]={100000,unsigned long(100000*options.gamma)};
    Gdiplus::PropertyItem property_item;

    property_item.id=PropertyTagGamma;
    property_item.length=sizeof(unsigned long)*2;
    property_item.type=PropertyTagTypeRational;
    property_item.value=&rational;
    output_bitmap->SetPropertyItem(&property_item);

    CLSID clsid;

    if(getEncoderCLSID(_T("image/png"),&clsid)>=0){
        //出力
        if(output_bitmap->Save(output_path,&clsid,NULL)==Gdiplus::Ok){
            ::MessageBox(handle(),
                         format(_T("'%s' を作成しました。"),output_path).c_str(),
                         (tstring(_T("MagicPNG Ver."))+SOFTWARE_VERSION).c_str(),
                         MB_ICONINFORMATION);
        }
    }

    SAFE_DELETE(src1_bitmap);
    SAFE_DELETE(src2_bitmap);
    SAFE_DELETE(output_bitmap);
}


Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > MainDialog.cpp