Your boss comes at your desk with a pile of CDs filled with high quality tiff images(roughly 20000 x 20000 pixels)
He tells you to print all the image files fit into a "letter" sized paper in 2 days
Well, that sort of stuff happend to me...
Man, was I frusted...
But that's when MSH came into rescue~
Well, the first thing that came up in my head was, "out-printer" cmdlet.
So I tried the following
MSH>$bitmap = new-object System.Drawing.Bitmap c:\test.tif
MSH>out-printer -printer "Adobe PDF" -in $bitmap
Voila. Now i was excited to see a picture in PDF format through "out-printer".
Wrong!
All I saw in the generated PDF file was
Tag :
PhysicalDimension : {Width=14454, Height=21957}
Size : {Width=14454, Height=21957}
Width : 14454
Height : 21957
HorizontalResolution : 1016
VerticalResolution : 1016
Flags : 77888
RawFormat : [ImageFormat: b96b3cb1-0728-11d3-9d7b-0000f81ef32e]
PixelFormat : Format1bppIndexed
Palette : System.Drawing.Imaging.ColorPalette
FrameDimensionsList : {7462dc86-6180-4c7e-8e3f-ee7333a7a483}
PropertyIdList : {256, 257, 258, 259, 262, 270, 273, 277, 278, 279, 282, 283, 32781}
PropertyItems : {256, 257, 258, 259, 262, 270, 273, 277, 278, 279, 282, 283, 32781}
, which is data you see just typing "MSH>$bitmap" in console.
Gosh, was I frusted, again. I looked into "out-printer" help page if there was some kind of "-encoding" option to print binary files(images) but there wans't any...
I resorted to using
System.Drawing.Printing.PrintDocumentWell, using that Class, printing is an image is a breezy job
So i created a cmdlet called "print-image" which takes an image name and print it
Here is the usage of the cmdlet
print-image "image name" [printer name] [fit image to paper]
The cmdlet takes the mandatory parameter "image name" with optional printer to print to and whether image size should fit on a paper
Following is how the cmdlet can be used
MSH> ls *.tif | foreach { print-image $_ }
Well and that's exactly what i did... :)
function print-image { param([string]$imageName = $(throw "Enter image name to print"), [string]$printer = "", [bool]$fitImageToPaper = $true)
trap { break; }
# check out Lee Holmes' blog(http://www.leeholmes.com/blog/HowDoIEasilyLoadAssembliesWhenLoadWithPartialNameHasBeenDeprecated.aspx) # on how to avoid using deprecated "LoadWithPartialName" function # To load assembly containing System.Drawing.Printing.PrintDocument [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# Bitmap image to use to print image $bitmap = $null
$doc = new-object System.Drawing.Printing.PrintDocument # if printer name not given, use default printer if ($printer -ne "") { $doc.PrinterSettings.PrinterName = $printer } $doc.DocumentName = [System.IO.Path]::GetFileName($imageName)
$doc.add_BeginPrint({ Write-Host "==================== $($doc.DocumentName) ====================" }) # clean up after printing... $doc.add_EndPrint({ if ($bitmap -ne $null) { $bitmap.Dispose() $bitmap = $null } Write-Host "xxxxxxxxxxxxxxxxxxxx $($doc.DocumentName) xxxxxxxxxxxxxxxxxxxx" }) # Adjust image size to fit into paper and print image $doc.add_PrintPage({ Write-Host "Printing $imageName..." $g = $_.Graphics $pageBounds = $_.MarginBounds $img = new-object Drawing.Bitmap($imageName) $adjustedImageSize = $img.Size $ratio = [double] 1; # Adjust image size to fit on the paper if ($fitImageToPaper) { $fitWidth = [bool] ($img.Size.Width > $img.Size.Height) if (($img.Size.Width -le $_.MarginBounds.Width) -and ($img.Size.Height -le $_.MarginBounds.Height)) { $adjustedImageSize = new-object System.Drawing.SizeF($img.Size.Width, $img.Size.Height) } else { if ($fitWidth) { $ratio = [double] ($_.MarginBounds.Width / $img.Size.Width); } else { $ratio = [double] ($_.MarginBounds.Height / $img.Size.Height) } $adjustedImageSize = new-object System.Drawing.SizeF($_.MarginBounds.Width, [float]($img.Size.Height * $ratio)) } }
# calculate destination and source sizes $recDest = new-object Drawing.RectangleF($pageBounds.Location, $adjustedImageSize) $recSrc = new-object Drawing.RectangleF(0, 0, $img.Width, $img.Height) # Print to the paper $_.Graphics.DrawImage($img, $recDest, $recSrc, [Drawing.GraphicsUnit]"Pixel") $_.HasMorePages = $false; # nothing else to print }) $doc.Print() }
|
Oh yeah, I would appreciate it if anyone can tell me how i can format the code to fit on to the site :)
Tags :
Monad msh
Nice solution,
ReplyDeleteb.t.w. did you think about landscape I think there is a rotating script on the monad team blog
greetings /\/\o\/\/
P.S. I formated my blog to the code ;-(
Thanks for the info there, /\/\o\/\/.
ReplyDeleteWell, I could modify the cmdlet to support landscape printing as well as duplex, and collate since they are part of PrinterSettings's properties.
Extending would be fun but, I think i will be converting the script into a Snapin if I need support more features :)
I did see you last post,
ReplyDeleteGuess you did feel like it;-)
thx,
gr /\/\o\/\/
Nice!!
ReplyDeleteBut... when I try it on a multipage tif it only prints the first page. Any ideas why?
//Rob
*bump* Any ideas on loading in pages from a multipage tiff?
ReplyDeleteIt can be use on pdf convert to a multipage tiff!
ReplyDeleteException calling "Print" with "0" argument(s): "Exception calling ".ctor" with "1" argument(s): "Parameter is
ReplyDeletenot valid.""
Why would I be getting this?
Also getting this, curious if anyone ever found a resolution.
ReplyDeleteException calling "Print" with "0" argument(s): "Exception calling ".ctor" with "1" argument(s): "Parameter is
not valid.""
Got this to work, thank you. See below for some info:
ReplyDeletePrint-Image -ImageName C:\Temp\image.png -printer Xerox6055Sales
My missing piece was the include the full path to the image with the ImageName parameter.
Can confirm this worked. Hope it helps.
Updated it to do multipage TIFFs. I am sure mine can be improved upon. Thanks for the base script!
ReplyDelete------------------------------------------------------------------
$rootdir = 'C:\Temp\pdf2tiff\'
$File = 'SomeMultiPage.tiff'
##Set path to print to PDF before merge
$TextDocumentPath = ($rootdir+$File )
# Get the path to the TIFF image file
$imagePath = $TextDocumentPath
# Create a PrintDocument object
$printDocument = New-Object System.Drawing.Printing.PrintDocument
$printDocument.DocumentName = $TextDocumentPath
# Set the printer name to 'Microsoft Print to PDF'
$printDocument.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$printDocument.PrinterSettings.PrintToFile = $true
$streamToPrint = New-Object System.IO.StreamReader $TextDocumentPath
# Set the page settings to fit the image to the page
$printDocument.DefaultPageSettings.Landscape = $false
#Set file export location
$file=[io.fileinfo]$TextDocumentPath
$pdf= [io.path]::Combine($file.DirectoryName, $file.BaseName) + '.pdf'
$printDocument.PrinterSettings.PrintFileName = $pdf
# Add an event handler for the PrintPage event and set page # outside handler
$script:pageNumber=0
$printDocument.add_PrintPage({
param($sender, $e)
# Load the image into a Bitmap object
$image = New-Object System.Drawing.Bitmap $imagePath
$image.SelectActiveFrame($image.FrameDimensionsList[0],$script:pageNumber)
$g = $e.Graphics
$pageBounds = $e.MarginBounds
$adjustedImageSize = $image.Size
$ratio = [double] 1;
# Adjust image size to fit on the paper
$fitWidth = [bool] ($image.Size.Width > $image.Size.Height)
if (($image.Size.Width -le $e.MarginBounds.Width) -and ($image.Size.Height -le $e.MarginBounds.Height)) {
$adjustedImageSize = new-object System.Drawing.SizeF($image.Size.Width, $image.Size.Height)
} else {
if ($fitWidth) {
$ratio = [double] ($e.MarginBounds.Width / $image.Size.Width);
} else {
$ratio = [double] ($e.MarginBounds.Height / $image.Size.Height)
}
$adjustedImageSize = new-object System.Drawing.SizeF($e.MarginBounds.Width, [float]($image.Size.Height * $ratio))
}
# calculate destination and source sizes
$recDest = new-object Drawing.RectangleF($pageBounds.Location, $adjustedImageSize)
$recSrc = new-object Drawing.RectangleF(0, 0, $image.Width, $image.Height)
# Print to the paper
$e.Graphics.DrawImage($image, $recDest, $recSrc, [Drawing.GraphicsUnit]"Pixel")
# Increment the page number
$script:pageNumber++
# Set the HasMorePages property based on the number of pages in the image
$e.HasMorePages = $script:pageNumber -lt $image.GetFrameCount([System.Drawing.Imaging.FrameDimension]::Page)
})
# Print the document
$printDocument.Print()
$streamToPrint.Close()
$printDocument.Dispose()
Above Script update posted by Sam F. ^^
ReplyDelete