批处理之家's Archiver

5i365 发表于 2022-5-24 14:18

PowerShell怎样将截图png质量改成256色

找了如下一段代码, 可以将屏幕截图, 可设质量, 但我想保存为256色的png图片, 如何设置? 请求路过高手指引, 提前感谢![code]function scr {
        param (
                [string]$location,
                [int]$quality,
                [switch]$allscreen
        )
        Add-Type -AssemblyName system.windows.Forms
        if ($allscreen.IsPresent)
        {
                $Capture = [system.windows.Forms.screen]::Allscreens
        }
        else
        {
                $Capture = [system.windows.Forms.Screen]::Primaryscreen
        }
        if ($Allscreens)
        {
                $Capture = [system.windows.Forms.screen]::Allscreens
        }
        else
        {
                $Capture = [system.windows.Forms.Screen]::PrimaryScreen
        }
        foreach ($C in $Capture)
        {
                $filename = $location + (get-date).ToString("yyy-M-dd-H-ss") + ".png"
                $Bitmap = New-object System.Drawing.Bitmap($C.Bounds.width, $C.Bounds.Height)
                $G = [System.Drawing.Graphics]::FromImage($Bitmap)
                $G.CopyFromscreen($C.Bounds.Location, (New-object system.Drawing.Point(0, 0)), $C.Bounds.Size)
                $G.Dispose()
                $Encoderparam = [system.Drawing.Imaging.Encoder]::Quality
                $Encoderparamset = New-object System.Drawing.Imaging.EnCoderparameters(1)
                $Encoderparamset.Param[0] = New-object system.Drawing.Imaging.Encoderparameter($Encoderparam, $Quality)
                $JPGCodec = [system.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | where{
                        $_.MimeType -eq 'image/png' #可设 jpeg  gif png                }
                $Bitmap.Save($FileName, $JPGCodec, $Encoderparamset)
        }
        
}

scr -location "C:\Users\Administrator\Desktop\" -quality 80 -allscreen [/code]

5i365 发表于 2022-5-24 18:28

另存为gif 颜色数就256了, 但是有好多噪点, 我从png手动另存为gif就没有噪点, 期待高手指引一下

5i365 发表于 2022-5-24 18:49

国外找了段代码, 但是一直报错[code]
# PowerShell gif encoding + wrapper around https://www.developerfusion.com/code/4630/capture-a-screen-shot/

Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
namespace GDI
{
    /// <summary>
    /// Provides functions to capture the entire screen, or a particular window, and save it to a file.
    /// </summary>
    public class ScreenCapture
    {
        /// <summary>
        /// Creates an Image object containing a screen shot of the entire desktop
        /// </summary>
        /// <returns></returns>
        public Image CaptureScreen()
        {
            return CaptureWindow( User32.GetDesktopWindow() );
        }
        /// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <returns></returns>
        public Image CaptureWindow(IntPtr handle)
        {
            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle,ref windowRect);
            int width = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
            // bitblt over
            GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);
            // restore selection
            GDI32.SelectObject(hdcDest,hOld);
            // clean up
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle,hdcSrc);
            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);
            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);
            return img;
        }
        /// <summary>
        /// Captures a screen shot of a specific window, and saves it to a file
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        public void CaptureWindowToFile(IntPtr handle, string filename, ImageFormat format)
        {
            Image img = CaptureWindow(handle);
            img.Save(filename,format);
        }
        /// <summary>
        /// Captures a screen shot of the entire desktop, and saves it to a file
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        public void CaptureScreenToFile(string filename, ImageFormat format)
        {
            Image img = CaptureScreen();
            img.Save(filename,format);
        }
      
        /// <summary>
        /// Helper class containing Gdi32 API functions
        /// </summary>
        private class GDI32
        {
            
            public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
            [DllImport("gdi32.dll")]
            public static extern bool BitBlt(IntPtr hObject,int nXDest,int nYDest,
                int nWidth,int nHeight,IntPtr hObjectSource,
                int nXSrc,int nYSrc,int dwRop);
            [DllImport("gdi32.dll")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC,int nWidth,
                int nHeight);
            [DllImport("gdi32.dll")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
            [DllImport("gdi32.dll")]
            public static extern bool DeleteDC(IntPtr hDC);
            [DllImport("gdi32.dll")]
            public static extern bool DeleteObject(IntPtr hObject);
            [DllImport("gdi32.dll")]
            public static extern IntPtr SelectObject(IntPtr hDC,IntPtr hObject);
        }

        /// <summary>
        /// Helper class containing User32 API functions
        /// </summary>
        private class User32
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
            [DllImport("user32.dll")]
            public static extern IntPtr GetDesktopWindow();
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowDC(IntPtr hWnd);
            [DllImport("user32.dll")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDC);
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowRect(IntPtr hWnd,ref RECT rect);
        }
    }
}
'@ -Language CSharp -ReferencedAssemblies system.drawing

function Capture-Screen
{
        param (
                [GDI.ScreenCapture]$SC
        )
        $Filename = Join-Path $PWD "capt$(Date -Format yyMMddhhmmssffff).bmp"
        $SC.CaptureWindowToFile((Get-Process -Id $PID).MainWindowHandle, $Filename, 'Bmp')
}

# Generate some random output, take screenshots
0 .. 10 | %{
        Get-Random
        Capture-Screen -SC $sc
        Start-Sleep -Milliseconds 200
}

$enc = [System.Windows.Media.Imaging.GifBitmapEncoder]::new()
foreach ($frame in Get-ChildItem .\capt*.bmp)
{
        $bmp = [System.Drawing.Bitmap]::FromFile($frame.FullName)
        $hbmp = $bmp.GetHbitMap()
        $bmpsrc = [System.Windows.Interop.Imaging]::CreateBitmapSourceFromHBitmap($hbmp, [System.IntPtr]::Zero, 'Empty', [System.Windows.Media.Imaging.BitmapSizeOptions]::FromEmptyOptions())
        $enc.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($bmpsrc))
        $hbmp = $bmp = $null
}

$filestream = [System.IO.File]::Create((Join-Path $PWD output.gif))
$enc.Save($filestream)
Remove-Item .\capt*.bmp

[/code]

523066680 发表于 2022-5-24 19:28

这是不是绕了什么弯路?
虽然不懂Powershell

5i365 发表于 2022-5-24 20:14

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=256048&ptid=62826]4#[/url] [i]523066680[/i] [/b]

有可能

gg搜索了一下, C#实现 png转8位256色png, 是个"世界难题", 好多解决办法都用别的组件了, 或用很长的代码实现的 :lol
存成gif是现成的, 但是会有噪点, 坐等高手指路

5i365 发表于 2022-5-24 21:29

[i=s] 本帖最后由 5i365 于 2022-5-24 21:32 编辑 [/i]

gif解决噪点, 找到一个文章, 但是不能下载, 估计很麻烦,
[url=https://www.cnblogs.com/mier/archive/2009/04/26/1443699.html]https://www.cnblogs.com/mier/archive/2009/04/26/1443699.html[/url]
哎, 感觉自己解决问题, 好吃力, 遇到的问题, 都是难题, 还是我水平太low了 :dizzy:

idwma 发表于 2022-5-24 23:39

一楼的改一下27行试试[code]$Bitmap = New-object System.Drawing.Bitmap($C.Bounds.width, $C.Bounds.Height,198659)
#https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.bitmap.-ctor#system-drawing-bitmap-ctor(system-int32-system-int32-system-int32-system-drawing-imaging-pixelformat-system-intptr)
#https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.imaging.pixelformat[/code]

5i365 发表于 2022-5-25 06:57

[i=s] 本帖最后由 5i365 于 2022-5-25 07:00 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=256062&ptid=62826]7#[/url] [i]idwma[/i] [/b]


   感谢大侠指引, 加上后,会报如下错误, 并生成了一个全黑的图片
ERROR: Exception calling "FromImage" with "1" argument(s): "A Graphics object cannot be created from an image that has an indexed pixel format."
我需要的就是将屏幕截为一张
没有噪点的gif图片
或者8位的png图片, 都可以, 因为别的格式图片体积太大了

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.