7

I need to convert all images in folder and subfolders to jpg. I need to batch this process with command file. GUI tools needles for me I need the script.

I tried to use mogrify.exe from ImageMagick, there is also convert.exe function, but afaik both of them are able to convert images.

I wrote next script:

$rootdir = "E:\Apps\скрипты\temp1\graphics"
$files = dir -r -i *.png $rootdir
foreach ($file in $files) {.\mogrify.exe -format png *jpg $file}

But it is not work, when I try to run it, I got errors:

mogrify.exe: unable to open file `*jpg' @ error/png.c/ReadPNGImage/3633.
mogrify.exe: Improper image header `E:\Apps\скрипты\temp1\graphics\telluric\day\
Athens\2011-07-03-17.png' @ error/png.c/ReadPNGImage/3641.
mogrify.exe: unable to open image `*jpg': Invalid argument @ error/blob.c/OpenBl
ob/2588.

Also I have find next code:

[Reflection.Assembly]::LoadWithPartialName('System.Drawing')

$img=[Drawing.Image]::FromFile("$(cd)\Max.jpg")
$img.Save("$(cd)\max.gif", 'Gif')
$img.Dispose()

How I can get it work with tree of dirs and convert png and tiff to jpg?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Suliman
  • 71
  • 1
  • 1
  • 3

2 Answers2

18

I've done something similar with converting a bitmap files to icon files here:

http://sev17.com/2011/07/creating-icons-files/

I adapted it to your requirements and test a function for converting image files to jpg:

function ConvertTo-Jpg
{
    [cmdletbinding()]
    param([Parameter(Mandatory=$true, ValueFromPipeline = $true)] $Path)

    process{
        if ($Path -is [string])
        { $Path = get-childitem $Path }

        $Path | foreach {
            $image = [System.Drawing.Image]::FromFile($($_.FullName));
            $FilePath = [IO.Path]::ChangeExtension($_.FullName, '.jpg');
            $image.Save($FilePath, [System.Drawing.Imaging.ImageFormat]::Jpeg);
            $image.Dispose();
        }
    }

 }

 #Use function:
 #Cd to directory w/ png files
 cd .\bin\pngTest

 #Run ConvertTo-Jpg function
 Get-ChildItem *.png | ConvertTo-Jpg
Ross Presser
  • 6,027
  • 1
  • 34
  • 66
Chad Miller
  • 40,127
  • 3
  • 30
  • 34
  • Looks good; though I would use `[IO.Path]::ChangeExtension( $_.FullName, '.jpg' )` rather than the manual string formatting. – Emperor XLII Dec 24 '11 at 22:55
  • ChangeExtension changes the extension of an existing file. I wouldn't want to change the original file. – Chad Miller Dec 28 '11 at 15:25
  • ChangeExtension REFORMATS A PATH string so it is pointing to a file with a different extension (and that file may not exist). It does nothing to files. That's why its in IO.Path and not IO.File or IO.Directory namespace. – Ross Presser Mar 15 '17 at 19:09
0

I adapted Chad Miller's answer to incorporate the ability to set JPEG's quality level from this blog post:
Benoît Patra's blog: Resize image and preserve ratio with Powershell

# Try uncommenting the following line if you receive errors about a missing assembly
# [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function ConvertTo-Jpg
{
  [cmdletbinding()]
  param([Parameter(Mandatory=$true, ValueFromPipeline = $true)] $Path)

  process{
    $qualityEncoder = [System.Drawing.Imaging.Encoder]::Quality
    $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)

    # Set JPEG quality level here: 0 - 100 (inclusive bounds)
    $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($qualityEncoder, 100)
    $jpegCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | where {$_.MimeType -eq 'image/jpeg'}

    if ($Path -is [string]) {
      $Path = get-childitem $Path
    }

    $Path | foreach {
      $image = [System.Drawing.Image]::FromFile($($_.FullName))
      $filePath =  "{0}\{1}.jpg" -f $($_.DirectoryName), $($_.BaseName)
      $image.Save($filePath, $jpegCodecInfo, $encoderParams)
      $image.Dispose()
    }
  }
}

#Use function:
# cd to directory with png files
cd .\bin\pngTest


#Run ConvertTo-Jpg function
Get-ChildItem *.png | ConvertTo-Jpg
Community
  • 1
  • 1
ComFreek
  • 29,044
  • 18
  • 104
  • 156
  • Getting inverted colors from a PNG with an alpha channel. Any idea how to fix that? – Ross Presser Mar 15 '17 at 19:58
  • @RossPresser I don't know by myself, but a quick search led to this [answer](http://stackoverflow.com/q/6513633/603003). Note that System.Drawing.Image is pure .NET API, so any answer making use of .NET (be it in C# or PS) can be "translated". – ComFreek Mar 15 '17 at 20:06
  • Interesting. I ended up just copying the 42 images to another machine where I could use imagemagick. But I'll keep in mind for someday. – Ross Presser Mar 16 '17 at 03:18