Home > Enterprise >  edit an image in place
edit an image in place

Time:09-28

So I've got a small script which opens an image:

    $file = ([System.IO.FileInfo]$FilePath);
    if ($file.Exists) {
        $imgInMemory = [System.Drawing.Image]::FromFile($file.FullName);
        [...irrelevant code to the question...]
        $imgInMemory.Save($($file.FullName   '.tmp'), $codecInfo, $encoderParams);
        Move-Item -Path $($file.FullName   '.tmp') -Destination $file.FullName -Force;
    }

So, I load the file contents with the Image.FromFile method, and I'm trying to save it back to the same filename. I have tried:

  1. $imgInMemory.Dispose() and $graphics.Dispose() followed by the .tmp save call and the move-item call seen above. This still gives an access denied exception.

What am I missing in terms of an open file handle because it would appear that even a -Force on the move-item only removes the .tmp file without overwriting the original file. So if you're doing something, like adding pins to an image, is it possible to save the output back to the original file? And if so, how?

CodePudding user response:

You can do this process without the need to create a temporary file, it's unclear why your code could be failing though this should work:

  1. Open the file to be overwritten with ReadWrite FileAccess.
  2. Use the FromStream method on the input file..
  3. SetFileLength to 0 for the input file before saving the new content to it.
  4. Use either Save(Stream, ImageCodecInfo, EncoderParameters) or Save(Stream, ImageFormat) overloads.
  5. Lastly, call Dispose on all variables.
using namespace System.IO
using namespace System.Drawing
using namespace System.Drawing.Imaging

Add-Type -AssemblyName System.Drawing

$inFile   = [FileInfo] 'path\to\file1.ext'
$refFile  = 'path\to\file2.ext'

if ($file.Exists) {
    $inStream  = $inFile.Open([FileMode]::Open, [FileAccess]::ReadWrite)

    $inImg  = [Image]::FromStream($inStream)
    $refImg = [Image]::FromFile($refFile)

    # irrelevant code here...

    $inStream.SetLength(0)
    $inImg.Save($inStream, $imageCodecInfo, $encoderParams)
    $refImg, $inImg, $inStream | ForEach-Object Dispose
}
  • Related