6

I'm making a tool that automates cropping and positioning w/out resizing an image into an other image. I found this on microsoft docs for .NET, but I cannot understand how to implement in my code. So far I can download images from the Mojang API, like:

Bernd_L.png
Bernd_L.png

Steve.png
Steve

I was wondering if I could crop a rectangle of 8x8 pixel at coordinates of 8,0 1.png and paste it on top of Steve.png at coordinates 8,8 so at the end the output will look like this:

output.png
output.png

How should I use .NET function .DrawImage to achieve the crop?

EDIT

Thanks to the link provided by @Caramiriel I can finally crop an area of the image with this script:

Add-Type -AssemblyName System.Drawing

$Username = "Steve"

$destRect = new-object Drawing.Rectangle 8, 0, 8, 8
$srcRect = new-object Drawing.Rectangle 0, 8, 8, 8
$src=[System.Drawing.Image]::FromFile("$pwd\$Username.png")
$bmp=new-object System.Drawing.Bitmap 64,64
$graphics=[System.Drawing.Graphics]::FromImage($bmp)
$units = [System.Drawing.GraphicsUnit]::Pixel
$graphics.DrawImage($src, $destRect, $srcRect, $units)
$graphics.Dispose()
$bmp.Save("$pwd\output.png")

If there's a more compact/elegant way to do it I would really like to know it!

EDIT 2

I posted an answer with a generic function to do the job.

DadiBit
  • 769
  • 10
  • 22
  • 3
    Anything that is available for c# is also available for powershell. If you find a good example/implementation you can convert the c# code to a powershell script. For example: https://stackoverflow.com/questions/734930/how-to-crop-an-image-using-c – Caramiriel Mar 05 '19 at 10:52
  • 2
    Abstract the rectangle-copying away in a separate function if you want a more compact/elegant script :) Also, please feel free to post your solution as an answer (self-answering is fine, encouraged even + you get repution points) :) – Mathias R. Jessen Mar 05 '19 at 13:30

1 Answers1

5

As suggested by @Mathias R. Jessen I used a function so it looks more elegant:

Add-Type -AssemblyName System.Drawing

$Username="Steve"

$bmp=new-object System.Drawing.Bitmap 64,64
$graphics=[System.Drawing.Graphics]::FromImage($bmp)
$src=[System.Drawing.Image]::FromFile("$pwd\$Username.png")
$units = [System.Drawing.GraphicsUnit]::Pixel

function DrawCroppedImage {
    param( [int]$srcX, [int]$srcY, [int]$srcWidth, [int]$srcHeight, [int]$destX, [int]$destY, [int]$destWidth, [int]$destHeight )
    $destRect = new-object Drawing.Rectangle $destX, $destY, $destWidth, $destHeight
    $srcRect = new-object Drawing.Rectangle $srcX, $srcY, $srcWidth, $srcHeight
    $graphics.DrawImage($src, $destRect, $srcRect, $units)
}

DrawCroppedImage 8 0 8 8 8 0 8 8

$graphics.Dispose()
$bmp.Save("$pwd\1.png")

So I can repeat it w/out rewriting all the code again for each single crop. I would like to add the fact that if you scale it (last two integers = 16) but you want to make it without any Interpolation you can use the same function but with two lines more:

function DrawCroppedImage {
    param( [int]$SrcX, [int]$SrcY, [int]$SrcWidth, [int]$SrcHeight, [int]$DestX, [int]$DestY, [int]$DestWidth, [int]$DestHeight )
    $DestRect = new-object Drawing.Rectangle $DestX, $DestY, $DestWidth, $DestHeight
    $SrcRect = new-object Drawing.Rectangle $SrcX, $SrcY, $SrcWidth, $SrcHeight
    //these two
    $graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::NearestNeighbor
    $graphics.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::Half
}

Found via this thread

DadiBit
  • 769
  • 10
  • 22