9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

クリップボードへコピーして画像を保存

Last updated at Posted at 2015-02-19

WPFなアプリケーションで 画像をクリップボード経由で保存する関数をつくりました
(何かドキュメントを勘違いして読んでた)
高度な関数にするほどでもなく使いどころが限定されすぎる
作った理由はExcel写真帳

.ps1
function Export-ClipboardToJpg{
  [OutputType([Void])]
  param($filepath)
  #クリップボードから画像を取り出してエンコード・保存
  $pic = [System.Windows.Clipboard]::GetImage();
  $enc = New-Object System.Windows.Media.Imaging.JpegBitmapEncoder;
  $enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($pic));
  $fs = New-Object system.IO.FileStream -ArgumentList "$filepath",'Create','Write'
  $enc.Save($fs);
  $fs.Close();
  return
}

System.Windows.Media.Imaging.JpegBitmapEncoderを変更すればPNG,BMP,TIFFにも変更可

####高度な関数
よくわからないが需要があるようなので高度な関数にやっつけた
jpg,png,tif,bmpに同時出力可(Excel写真帳弄ってたらjpgとtifでくれといわれたりするような奴は俺以外にもいるはず。いると言え。 orz)

.ps1
function Export-ClipboardToImage{
	[CmdletBinding()]
	[OutputType([Void])]  
	param(
		[parameter(
			mandatory   = $false,
			helpmessage = '出力先のフォルダを指定。指定がない場合ユーザのマイドキュメントへ出力'
		)]
		[string]$destination =  [Environment]::GetFolderPath('MyDocuments'),
		[parameter(
			mandatory   = $true,
			helpmessage = 'ファイル名。拡張子不要'
		)]
		[string]$basename =  '',
		[parameter(
			mandatory   = $false,
			helpmessage = '.jpgで出力。スイッチがつかない場合デフォルトでjpg'
		)]
		[switch]$jpg,
		[parameter(
			mandatory   = $false,
			helpmessage = '.pngで出力'
		)]
		[switch]$png,  
		[parameter(
			mandatory   = $false,
			helpmessage = '.tifで出力'
		)]
		[switch]$tif,  
		[parameter(
			mandatory   = $false,
			helpmessage = '.bmpで出力'
		)]
		[switch]$bmp
	)
	begin{
		#出力先フォルダがあるかチェック
		if(Test-Path $destination){
			$path = $(Get-Item $($destination+'\')).fullname + $basename;
		}
		else{
			throw "出力先:$destination が存在しません";
		}
		#出力形式
		if( -not $($jpg -or $png -or $bmp -or $tif)){
			$jpg = $true;
		};
	}
	process{
		#クリップボードから画像を取り出してエンコード・保存
		if(-not [System.Windows.Clipboard]::ContainsImage()){
			throw 'クリップボードに画像がない';
		}
		$pic = [System.Windows.Clipboard]::GetImage();
		#出力
		if($jpg){
			$filepath = $path + '.jpg'
			$enc = New-Object System.Windows.Media.Imaging.JpegBitmapEncoder;
			$enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($pic));
			$fs = New-Object system.IO.FileStream -ArgumentList "$filepath",'Create','Write';
			$enc.Save($fs);
			$fs.Close();
		}
		if($png){
			$filepath = $path + '.png'
			$enc = New-Object System.Windows.Media.Imaging.PngBitmapEncoder;
			$enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($pic));
			$fs = New-Object system.IO.FileStream -ArgumentList "$filepath",'Create','Write';
			$enc.Save($fs);
			$fs.Close();
		}
		if($tif){
			$filepath = $path + '.tif'
			$enc = New-Object System.Windows.Media.Imaging.TiffBitmapEncoder;
			$enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($pic));
			$fs = New-Object system.IO.FileStream -ArgumentList "$filepath",'Create','Write';
			$enc.Save($fs);
			$fs.Close();
		}
		if($bmp){
			$filepath = $path + '.bmp'
			$enc = New-Object System.Windows.Media.Imaging.BmpBitmapEncoder;
			$enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($pic));
			$fs = New-Object system.IO.FileStream -ArgumentList "$filepath",'Create','Write';
			$enc.Save($fs);
			$fs.Close();
		}
	}
	end{
		return  
	}
}

#####以下こんな風に使う例

.ps1
#example
$path = 'X:\xls\'
$OutPath = 'X:\jpg\'
try{
#Excelオブジェクトの作成
$xls_app = New-Object -ComObject Excel.Application
#Excelを画面に表示する
$xls_app.Visible = $false
$xls_app.ScreenUpdating = $false
#Excelの警告をオフ
$xls_app.DisplayAlerts = $false

Get-ChildItem -Path $path -File -Filter '*.xls'|%{
  $xls_file  = $_.fullname
  $basename  = $_.basename
  $xls_books = $xls_app.Workbooks.Open("$xls_file")
  $cnt_exlws = $xls_books.Worksheets.Count
  #シートへ接続
  $xls_sheet = $xls_books.Worksheets.Item(1)
  $xls_sheet.Activate()
  $ws_name   = $xls_sheet.Name
  #写真を取得
  $ary_shapes = @()
  $cnt_shapes = $xls_sheet.Shapes.Count
  if($cnt_shapes -eq 0){break}
  $i = 1
  do{
    $ary_shapes += $xls_sheet.Shapes.Item($i);
    $i++
  }until($i -gt $cnt_shapes);
  #leftの位置が小さい方が近景
  $near = $ary_shapes|
  Where-Object -Property AutoShapeType -EQ 1|
  Sort-Object -Property left |
  Select-Object -First 1;
 $near.ScaleHeight(1,$true,1);
 $near.ScaleWidth(1,$true,1);
  $near.Copy();
  Export-ClipboardToJpg -filepath $($OutPath+$basename+'_'+'near.jpg');
  
  #leftの位置が大きい方が遠景
  $far  = $ary_shapes|
  Where-Object -Property AutoShapeType -EQ 1|
  Sort-Object -Property left |
  Select-Object -Last 1;
 $far.ScaleHeight(1,$true,1);
 $far.ScaleWidth(1,$true,1);
  $far.Copy();
  Export-ClipboardToJpg -filepath $($OutPath+$basename+'_'+'far.jpg');
  #ブックのクローズ
  $xls_books.Close($false) ;
}
}finally{
#region end  
  #Excelの警告をon
  #Excelを画面に表示する
  $xls_app.Visible = $true
  $xls_app.ScreenUpdating = $true
  $xls_app.DisplayAlerts = $true
  #Excelのクローズ
  #comオブジェクト操作なのでPSから指示しないとexcelのプロセスが残る
  #quit()の後、操作に使った変数にnullを入れて開放する、戻り値なし(out-null)
  $xls_app.Quit()
  foreach($obj in $xls_sheet,$xls_books,$xls_app){
      [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($obj)|Out-Null
  }
  #ガベージコレクタを動作させる
  [GC]::Collect();
  Write-Host("終了")
#region
}
9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?