Home > ソフトウェア > Ashley > Ashley130.zip/Ashley130.exe > Src > Thumbnail.cpp
//Thumbnail.cpp //書庫ファイル内の画像のサムネイルをHBITMAPで取得 /*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# Ashley Ver.1.30 Coded by x@rgs This code is released under NYSL Version 0.9982 See NYSL_withfaq.TXT for further details. Ashleyは、アップローダからダウンロードしたZIPやRAR等のファイル名を元に戻すソフトです。 #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*/ #include"Pch.h" #include"Thumbnail.h" #include"UnZipFile.h" #include"UnRarFile.h" #include"ArcDll.h" #include"Path.h" #include"Function.h" #include"resources/resource.h" #include<olectl.h> #include<shlwapi.h> #include<gdiplus.h> //サムネイル最大バッファ(32MB) #define THUMBNAIL_MAX_BUFFERSIZE 33554432 using namespace std; //対応している画像の拡張子かどうか bool IsSupportedImage(const TCHAR* pszPath){ TCHAR szExtension[_MAX_EXT]={0}; _tcscpy(szExtension,PathFindExtension(pszPath)); if(_tcsicmp(szExtension,_T(".bmp"))==0)return true; if(_tcsicmp(szExtension,_T(".gif"))==0)return true; if(_tcsicmp(szExtension,_T(".ico"))==0)return true; if(_tcsicmp(szExtension,_T(".jpe"))==0)return true; if(_tcsicmp(szExtension,_T(".jpeg"))==0)return true; if(_tcsicmp(szExtension,_T(".jpg"))==0)return true; if(_tcsicmp(szExtension,_T(".jif"))==0)return true; if(_tcsicmp(szExtension,_T(".jfi"))==0)return true; if(_tcsicmp(szExtension,_T(".jfif"))==0)return true; if(_tcsicmp(szExtension,_T(".png"))==0)return true; if(_tcsicmp(szExtension,_T(".tif"))==0)return true; if(_tcsicmp(szExtension,_T(".tiff"))==0)return true; return false; } //16x16のダミーアイコンを描写したHBITMAPを作成 HBITMAP CreateDummyBitmap(int iWidth,int iHeight){ HICON hIcon=NULL; hIcon=static_cast<HICON>(LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_ICON_DUMMY),IMAGE_ICON,0,0,0)); HDC hDC=GetDC(NULL); HDC hWorkDC=CreateCompatibleDC(hDC); HBITMAP hBitmap=CreateCompatibleBitmap(hDC,iWidth,iHeight); HBITMAP hOldBitmap=(HBITMAP)SelectObject(hWorkDC,hBitmap); DrawIcon(hWorkDC,0,0,hIcon); SelectObject(hWorkDC,hOldBitmap); DeleteDC(hWorkDC); DestroyIcon(hIcon); ReleaseDC(NULL,hDC); return hBitmap; } //16x16のダミーアイコンを描写したHBITMAPを作成 HBITMAP CreateDummyBitmap2(HDC hdc, int iWidth,int iHeight){ HICON hIcon=NULL; hIcon=static_cast<HICON>(LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_ICON_DUMMY),IMAGE_ICON,0,0,0)); HDC hWorkDC=CreateCompatibleDC(hdc); HBITMAP hBitmap=CreateCompatibleBitmap(hdc,iWidth,iHeight); HBITMAP hOldBitmap=(HBITMAP)SelectObject(hWorkDC,hBitmap); DrawIcon(hWorkDC,0,0,hIcon); SelectObject(hWorkDC,hOldBitmap); DeleteDC(hWorkDC); DestroyIcon(hIcon); return hBitmap; } //ファイルパスからアイコンを取得しBitmapに変換 HBITMAP CreateBitmapFromPath(LPCTSTR lpszPath,int iWidth,int iHeight){ SHFILEINFO shFileInfo; HICON hIcon=NULL; HIMAGELIST hImageList=NULL; hImageList=(HIMAGELIST)SHGetFileInfo(lpszPath,0,&shFileInfo,sizeof(shFileInfo),SHGFI_ICON|SHGFI_LARGEICON|SHGFI_USEFILEATTRIBUTES|SHGFI_SYSICONINDEX); hIcon=ImageList_GetIcon(hImageList,shFileInfo.iIcon,ILD_NORMAL);//ILD_IMAGE ICONINFO IconInfo; IconInfo.fIcon=true;//アイコンである GetIconInfo(hIcon,&IconInfo); BITMAP Bitmap; GetObject(IconInfo.hbmColor,sizeof(Bitmap),&Bitmap); HDC hDC=GetDC(NULL); HDC hWorkDC=CreateCompatibleDC(hDC); SetStretchBltMode(hWorkDC,HALFTONE); //After setting the HALFTONE stretching mode, an application must call the SetBrushOrgEx function to set the brush origin. If it fails to do so, brush misalignment occurs. //(http://msdn.microsoft.com/en-us/library/dd145089(v=vs.85).aspx) SetBrushOrgEx(hWorkDC,0,0,NULL); HBITMAP hBitmap=CreateCompatibleBitmap(hDC,iWidth,iHeight); HBITMAP hOldBitmap=(HBITMAP)SelectObject(hWorkDC,hBitmap); POINT pt={(iWidth-Bitmap.bmWidth)>>1,(iHeight-Bitmap.bmHeight)>>1};//中央表示座標 DrawIcon(hWorkDC,pt.x,pt.y,hIcon); SelectObject(hWorkDC,hOldBitmap); DeleteDC(hWorkDC); DestroyIcon(shFileInfo.hIcon); DestroyIcon(hIcon); ReleaseDC(NULL,hDC); return hBitmap; } //IStreamからHBITMAPを取得 HBITMAP CreateBitmapFromIStream(IStream* pIStream,const LPSIZE psizeThumbnail){ Gdiplus::Bitmap* pBitmap=Gdiplus::Bitmap::FromStream(pIStream); if(pBitmap==NULL)return NULL; if(pBitmap->GetLastStatus()!=Gdiplus::Ok)return NULL; if(pBitmap->GetWidth()<=0||pBitmap->GetHeight()<=0)return NULL; int iSrcWidth=0,iSrcHeight=0; int iDestWidth=0,iDestHeight=0; iSrcWidth=pBitmap->GetWidth(); iSrcHeight=pBitmap->GetHeight(); if(psizeThumbnail->cx<iSrcWidth||psizeThumbnail->cy<iSrcHeight){ //サムネイルのキャンバスサイズより大きい float rX=(float)psizeThumbnail->cx/iSrcWidth; float rY=(float)psizeThumbnail->cy/iSrcHeight; iDestWidth=(int)(min(rX,rY)*iSrcWidth);//縮小後のサイズ iDestHeight=(int)(min(rX,rY)*iSrcHeight); }else{ //サムネイルのキャンバスサイズより小さい iDestWidth=iSrcWidth; iDestHeight=iSrcHeight; } HDC hdcScreen=GetDC(NULL); HBITMAP hbmpResult=CreateCompatibleBitmap(hdcScreen,psizeThumbnail->cx,psizeThumbnail->cy); HDC hdcMemory=CreateCompatibleDC(hdcScreen); SetBkMode(hdcMemory,TRANSPARENT); ReleaseDC(NULL,hdcScreen); HGDIOBJ hobjOld=SelectObject(hdcMemory,hbmpResult); const POINT ptDest={(psizeThumbnail->cx-iDestWidth)>>1,(psizeThumbnail->cy-iDestHeight)>>1};//中央表示座標 #if 1 Gdiplus::Graphics* pGraphics=Gdiplus::Graphics::FromHDC(hdcMemory); // pGraphics->SetInterpolationMode(Gdiplus::InterpolationModeInvalid); pGraphics->DrawImage(pBitmap,ptDest.x,ptDest.y,iDestWidth,iDestHeight); delete pGraphics; #else //TODO:7環境でCOLORONCOLORであれば必要なし //HALFTONEの場合、有効にすると真っ白け /* HICON hIcon=static_cast<HICON>(LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_ICON_DUMMY),IMAGE_ICON,0,0,LR_SHARED)); DrawIcon(hdcMemory,0,0,hIcon); DestroyIcon(hIcon); */ SetStretchBltMode(hdcMemory,HALFTONE);//COLORONCOLOR); Gdiplus::BitmapData bitmapData; pBitmap->LockBits(NULL,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB,&bitmapData); BITMAPINFOHEADER BitmapInfoHeader; memset(&BitmapInfoHeader,0,sizeof(BITMAPINFOHEADER)); BitmapInfoHeader.biSize=sizeof(BITMAPINFOHEADER); BitmapInfoHeader.biWidth=bitmapData.Width; BitmapInfoHeader.biHeight=bitmapData.Height; BitmapInfoHeader.biPlanes=1; BitmapInfoHeader.biBitCount=32; BitmapInfoHeader.biCompression=BI_RGB; BitmapInfoHeader.biClrUsed=0; BitmapInfoHeader.biClrImportant=0; StretchDIBits(hdcMemory, ptDest.x,ptDest.y+iDestHeight,iDestWidth,-iDestHeight, 0, 0,BitmapInfoHeader.biWidth,BitmapInfoHeader.biHeight, bitmapData.Scan0,(BITMAPINFO*)&BitmapInfoHeader, DIB_RGB_COLORS,SRCCOPY); pBitmap->UnlockBits(&bitmapData); #endif SelectObject(hdcMemory,hobjOld); DeleteDC(hdcMemory); return hbmpResult; } HBITMAP CreateBitmapFromMemory(LPCVOID lpcBuffer,const ULONG ulBufferSize,const LPSIZE psizeThumbnail){ HBITMAP hRetBitmap=NULL; HANDLE hBuffer=NULL; LPVOID lpBuffer=NULL; IStream* pIStream=NULL; //lpBuffer=(LPVOID)GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,ulBufferSize); hBuffer=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,ulBufferSize); if(hBuffer){ lpBuffer=GlobalLock(hBuffer); if(lpBuffer){ CopyMemory(lpBuffer,lpcBuffer,ulBufferSize); if(CreateStreamOnHGlobal(hBuffer,false,&pIStream)==S_OK){ hRetBitmap=CreateBitmapFromIStream(pIStream,psizeThumbnail);//IStreamからHBITMAP取得 pIStream->Release(); } } } GlobalUnlock(hBuffer); GlobalFree(hBuffer);//解放 hBuffer=NULL; return hRetBitmap; } //zipファイル内の画像のサムネイルをHBITMAPで取得 HBITMAP GetThumbnailBitmapFromZipFile(const TCHAR* pszFilePath,const int iWidth,const int iHeight){ bool bSuccess=false; int iCount=0;//格納ファイル数 int iThumbIndex=-1;//サムネイルとして利用する画像のIndex HBITMAP hRetBitmap=NULL; LPBYTE lpBuffer=NULL; SIZE sizeThumbnail; CUnZip UnZip; if(!UnZip.OpenFile(pszFilePath))return NULL;//書庫ファイルを開くことが出来ない iCount=UnZip.GetFileCount(); if(iCount==0)return NULL;//書庫内にファイルがない tstring strFileName; for(int i=0;i<iCount;i++){ if(!UnZip.GetFileInfo(i))break;//書庫ファイル内の情報を取得出来ない if(UnZip.IsDirectory())continue;//ディレクトリである if(UnZip.GetUncompressedSize()>THUMBNAIL_MAX_BUFFERSIZE)continue;//サムネイル最大バッファより大きい if(UnZip.GetCompressedSize()==0||UnZip.GetUncompressedSize()==0)continue;//ファイルサイズが0 if(IsSupportedImage(UnZip.GetFileName())){//対応している画像ファイルである if(iThumbIndex<0)iThumbIndex=i; if(strFileName.empty())strFileName=UnZip.GetFileName(); if(_StrCmpLogicalW(UnZip.GetFileName(),(PCWSTR)strFileName.c_str())==-1){//GetZipFileItemName()<strFileName iThumbIndex=i; strFileName=UnZip.GetFileName(); } } } if(iThumbIndex<0)return NULL; if(!UnZip.GetFileInfo(iThumbIndex))return NULL;//書庫ファイル内の情報を取得出来ない lpBuffer=(LPBYTE)HeapAlloc(GetProcessHeap(),0,UnZip.GetUncompressedSize()*sizeof(BYTE));//ファイルのバッファ確保 if(lpBuffer){ ZeroMemory(lpBuffer,UnZip.GetUncompressedSize()*sizeof(BYTE)); if(!UnZip.ExtractMem(iThumbIndex,lpBuffer,UnZip.GetUncompressedSize()))return NULL; //サムネイルサイズ設定 sizeThumbnail.cx=iWidth; sizeThumbnail.cy=iHeight; //HBITMAP取得 hRetBitmap=CreateBitmapFromMemory(lpBuffer,UnZip.GetUncompressedSize(),&sizeThumbnail); if(hRetBitmap!=NULL)bSuccess=true; else bSuccess=false; HeapFree(GetProcessHeap(),0,lpBuffer); lpBuffer=NULL; } return (bSuccess)?hRetBitmap:NULL; } //サムネイルとして利用する画像のIndexを取得 __int64 GetThumbnailIndexRAR(LPCTSTR lpszFilePath){ CUnRar UnRar; if(!UnRar.CheckReady())return -1;//DLLは使用可能な状況ではない if(!UnRar.OpenFile(lpszFilePath))return -1;//書庫ファイルを開くことが出来ない //ソリッド、マルチボリューム、ヘッダ暗号化書庫は無視する if(UnRar.IsArchiveSolid()||UnRar.IsArchiveVolume()||UnRar.IsArchiveEncryptedHeaders())return -1; UINT64 iPackedSize,iUnpackedSize; __int64 i=-1,iThumbIndex=-1; tstring strFileName; while(UnRar.ReadFileInfo()){ i+=1; iPackedSize=UnRar.GetFilePackedSize64(); iUnpackedSize=UnRar.GetFileUnpackedSize64(); if(UnRar.IsDirectory()||iUnpackedSize>THUMBNAIL_MAX_BUFFERSIZE||iPackedSize==0||iUnpackedSize==0){ UnRar.SkipFile(); continue; } if(IsSupportedImage(UnRar.GetFileName())){ if(iThumbIndex<0)iThumbIndex=i; if(strFileName.empty())strFileName=UnRar.GetFileName(); if(_StrCmpLogicalW(UnRar.GetFileName(),(PCWSTR)strFileName.c_str())==-1){//GetFileName()<strFileName iThumbIndex=i; strFileName=UnRar.GetFileName(); } } UnRar.SkipFile(); } return iThumbIndex; } //rarファイル内の画像のサムネイルをHBITMAPで取得 HBITMAP GetThumbnailBitmapFromRarFile(const TCHAR* pszFilePath,const int iWidth,const int iHeight){ __int64 iThumbIndex=-1;//サムネイルとして利用する画像のIndex HBITMAP hRetBitmap=NULL; SIZE sizeThumbnail; IStream* pIStream=NULL; CUnRar UnRar; if(!UnRar.CheckReady())return NULL;//DLLは使用可能な状況ではない iThumbIndex=GetThumbnailIndexRAR(pszFilePath); if(iThumbIndex<0)return NULL; if(!UnRar.OpenFile(pszFilePath,false))return NULL;///書庫ファイルを開くことが出来ない if(!UnRar.SkipFiles(iThumbIndex))return NULL; //ファイルの情報を読み込む if(!UnRar.ReadFileInfo())return NULL; //サムネイルサイズ設定 sizeThumbnail.cx=iWidth; sizeThumbnail.cy=iHeight; HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(SIZE_T)UnRar.GetFileUnpackedSize64()); if(hGlobal){ if(CreateStreamOnHGlobal(hGlobal,TRUE,(LPSTREAM*)&pIStream)==S_OK){ UnRar.SetIStream(pIStream); //HBITMAP取得 if(UnRar.ProcessFile())hRetBitmap=CreateBitmapFromIStream(pIStream,&sizeThumbnail); } } GlobalFree(hGlobal); pIStream->Release(); return (hRetBitmap!=NULL)?hRetBitmap:NULL; } //lzhファイル内の画像のサムネイルをHBITMAPで取得 HBITMAP GetThumbnailBitmapFromLHAFile(const TCHAR* pszFilePath,const int iWidth,const int iHeight){ bool bSuccess=false; bool bSuccessBitmap=false; int iCmdLineLength=0; LONGLONG llOriginalSize=0,llCompressedSize=0,llTargetOriginalSize=0; LPSTR lpszRetPath=NULL;//GetFileName()の引数 LPWSTR lpszRetPathW=NULL; HBITMAP hRetBitmap=NULL; TCHAR pszCmdLine[MAX_PATH*2]={0};//LPWSTR pszCmdLine=NULL;//DLLに渡すコマンド LPBYTE lpBuffer=NULL; SIZE sizeThumbnail; CArcDll ArcDll; if(!ArcDll.LoadDll(_T("UNLHA32.DLL"),_T("Unlha")))return NULL;//DLLを読み込むことが出来ない ArcDll.SetCursorMode(false);//DLL独自のカーソルを表示しない do{//ダミーループ do{//ダミーループ if(ArcDll.CheckArchiveW(pszFilePath,1)==false)break;//正しい書庫ファイルではない if(ArcDll.GetRunning())break;//DLLは動作中である if(ArcDll.OpenArchiveW(NULL,pszFilePath,0)==NULL)break;//書庫ファイルを開くことが出来ない bSuccess=true; }while(0); if(!bSuccess)return NULL; bSuccess=false; if(ArcDll.FindFirstA("*.*",NULL)==-1)break;//書庫ファイル内の情報を取得出来ない lpszRetPath=(LPSTR)malloc(MAX_PATH);//HeapAlloc(GetProcessHeap(),0,MAX_PATH); lpszRetPathW=(LPWSTR)malloc(MAX_PATH); tstring strFileName; do{ //GetFileNameW()だと失敗してしまう? //GetUserDefaultLangID() if(ArcDll.GetFileNameA(lpszRetPath,MAX_PATH)){ continue;//書庫ファイル内のファイル名を取得出来ない }else{ if(!MultiByteToWideChar(CP_ACP,0,lpszRetPath,-1,lpszRetPathW,MAX_PATH))continue;//変換失敗 } if(ArcDll.IsDirectory())continue;//ディレクトリである ArcDll.GetOriginalSizeEx(&llOriginalSize); ArcDll.GetCompressedSizeEx(&llCompressedSize); if(llOriginalSize>THUMBNAIL_MAX_BUFFERSIZE)continue;//サムネイル最大バッファより大きい if(llOriginalSize==0||llCompressedSize==0)continue;//ファイルサイズが0 if(IsSupportedImage(lpszRetPathW)){//対応している画像ファイルである if(strFileName.empty()){ strFileName=lpszRetPathW; llTargetOriginalSize=llOriginalSize; } if(_StrCmpLogicalW(lpszRetPathW,(PCWSTR)strFileName.c_str())==-1){//GetZipFileItemName()<strFileName strFileName=lpszRetPathW; llTargetOriginalSize=llOriginalSize; } bSuccess=true; break; } }while(ArcDll.FindNext(NULL)!=-1);//検索終了まで回す if(!bSuccess)break;//対応している画像が格納されていなかった bSuccess=false; ArcDll.CloseArchive(); iCmdLineLength=lstrlen(pszFilePath)+strFileName.size()+24; //pszCmdLine=(LPWSTR)malloc(iCmdLineLength);//HeapAlloc(GetProcessHeap(),0,iCmdLineLength); //if(pszCmdLine){ //n(展開状況ダイアログ表示の抑止) //gm(エラーメッセージ表示の抑止) wsprintf(pszCmdLine,_T("-n -gm \"%s\" \"%s\""),pszFilePath,strFileName.c_str()); lpBuffer=(LPBYTE)malloc(llTargetOriginalSize*sizeof(BYTE));//HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,llTargetOriginalSize*sizeof(BYTE));//ファイルのバッファ確保 if(lpBuffer){ if(ArcDll.ExtractMemW(NULL,pszCmdLine,lpBuffer,llTargetOriginalSize,NULL,NULL,NULL)==0){ //サムネイルサイズ設定 sizeThumbnail.cx=iWidth; sizeThumbnail.cy=iHeight; //HBITMAP取得 hRetBitmap=CreateBitmapFromMemory(lpBuffer,llOriginalSize,&sizeThumbnail); if(hRetBitmap!=NULL)bSuccessBitmap=true; else bSuccessBitmap=false; } free(lpBuffer);//HeapFree(GetProcessHeap(),0,lpBuffer); lpBuffer=NULL; //} //free(pszCmdLine);//HeapFree(GetProcessHeap(),0,pszCmdLine); //pszCmdLine=NULL; } bSuccess=true; }while(0); if(!bSuccess)ArcDll.CloseArchive(); free(lpszRetPath);//HeapFree(GetProcessHeap(),0,lpszRetPath); free(lpszRetPathW); return (bSuccess)?hRetBitmap:NULL; } HBITMAP GetThumbnailBitmapFromArchiveFile(const TCHAR* pszFilePath,const int iWidth,const int iHeight){ LPTSTR lpszExtension=NULL; HBITMAP hBitmap=NULL; lpszExtension=PathFindExtension(pszFilePath); if(_tcsicmp(lpszExtension,_T(".zip"))==0){ hBitmap=GetThumbnailBitmapFromZipFile(pszFilePath,iWidth,iHeight); }else if(_tcsicmp(lpszExtension,_T(".rar"))==0){ hBitmap=GetThumbnailBitmapFromRarFile(pszFilePath,iWidth,iHeight); }else if(_tcsicmp(lpszExtension,_T(".lzh"))==0){ hBitmap=GetThumbnailBitmapFromLHAFile(pszFilePath,iWidth,iHeight); } return hBitmap; }
Home > ソフトウェア > Ashley > Ashley130.zip/Ashley130.exe > Src > Thumbnail.cpp