Powershell >6.0... command line background color with ANSI sequences (PSReadLine) ?how? - powershell

In PowerShell >6.0 I can change the command line FOREGROUND colors with:
Set-PSReadLineOption -Colors #{ Keyword="#0FAFE0"; Variable="#987ABC" }+
but how do I change the BACKGROUND colors with RGB??? (#RRGGBB)
i can see some examples with ASCII console sequences
but none with the RGB format

I don't think you can? SelectionColor uses the ansi escape code for black on white: "`e[30;47m" (ps 7 for the `e). https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
How about this from that wikipeda page:
ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m -- choose RGB foreground color
ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m -- choose RGB background color
Red foreground (255 0 0) blue (0 0 255) background.
Set-PSReadLineOption -Colors #{ variable = "`e[38;2;255;0;0m" + # fg
"`e[48;2;0;0;255m" } # bg
In ps5 you have to say $([char]0x1b) instead of `e.
$e = [char]0x1b
Set-PSReadLineOption -Colors #{ variable = "$e[38;2;255;0;0m" + # fg
"$e[48;2;0;0;255m" } # bg

Related

How to use hex codes for color in Write-Host?

In Write-Host you can set the foreground color like
Write-Host "test" -ForegroundColor Green
Can you use hex codes? Like
Write-Host "test" -ForegroundColor FFFFFF
If I want the foreground color to be a color not listed in
[System.Enum]::GetValues([System.ConsoleColor])
What do I do?
I suppose you can get into escape codes like psreadline. Run "get-psreadlineoptions" to see some of them. The docs for that command have a link to the codes. https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_ In powershell 7 you can use "`e" for escape.
write-host "$([char]0x1b)[91mhi"
hi # appears red
Command "$([char]0x1b)[31m" red # 93 bright yellow
Comment "$([char]0x1b)[32m" green
ContinuationPrompt "$([char]0x1b)[37m" white # 33 yellow
DefaultToken "$([char]0x1b)[37m" white
Emphasis "$([char]0x1b)[96m" bright cyan
Error "$([char]0x1b)[91m" bright red
Keyword "$([char]0x1b)[92m" bright green
Member "$([char]0x1b)[97m" bright white
Number "$([char]0x1b)[97m" bright white
Operator "$([char]0x1b)[90m" bright black
Parameter "$([char]0x1b)[90m" bright black
Selection "$([char]0x1b)[30;47m" black on white # 35;43 magenta;yellow
String "$([char]0x1b)[36m" cyan
Type "$([char]0x1b)[37m" white
Variable "$([char]0x1b)[92m" bright green
There's a module called Pansies that does it.
It installs a new write-host.
https://www.reddit.com/r/PowerShell/comments/hi0c0v/module_monday_pansies/ It supports xterm colors too, DodgerBlue, etc...
Another option could be to create a hashtable map of hex codes and console color names and use that:
$colorMap = [ordered]#{
'000000' = 'Black'
'140E88' = 'DarkBlue'
'00640A' = 'DarkGreen'
'008B87' = 'DarkCyan'
'8B0000' = 'DarkRed'
'820087' = 'DarkMagenta'
'AAAA00' = 'DarkYellow'
'A9A9A9' = 'Gray'
'808080' = 'DarkGray'
'0000FF' = 'Blue'
'00FF00' = 'Green'
'00FFFF' = 'Cyan'
'FF0000' = 'Red'
'FF00FF' = 'Magenta'
'FFFF00' = 'Yellow'
'FFFFFF' = 'White'
}
foreach($colorCode in $colorMap.Keys) {
Write-Host "Testing color $colorCode" -ForegroundColor $colorMap[$colorCode]
}
Of course, using this you are restricted to the hex codes the $colorMap contains as key, otherwise an exception is thrown

I'm trying to change font color in One Note trough an autohotkey

Im using this code in the autohotkey converter because I would like to press for example:
'ctrl + alt + r' to change the font color
SetTitleMatchMode, RegEx ; match window titles by regular expressions
#IfWinActive - OneNote$ ; ------ only in windows with title ending with "- OneNote"
^!p::Send, !hfca!hfc{Down 7}{Right 4}{Enter}
^!r::Send, !hfcm^{PgDn}!r255{Tab}5{Tab}0{Enter} ; red (255, 0, 0)
^!b::Send, !hfcm^{PgDn}!r0{Tab}5{Tab}255{Enter} ; blue (0, 0, 255)
^!a::Send, !hfca ; automatic color (i.e. reset font color to "none")
#IfWinActive ; ------ end of section restricted to specific windows
I executed this code trough the .exe file but nothing happened

Ghostscript -- convert PS to PNG, rotate, and scale

I have an application that creates very nice data plots rendered in PostScript with letter size and landscape mode. An example of the input file is at http://febo.com/uploads/blip.ps. [ Note: this image renders properly in a viewer, but the PNG conversion comes out with the image sideways. ] I need to convert these PostScript files into PNG images that are scaled down and rotated 90 degrees for web presentation.
I want to do this with ghostscript and no other external tool, because the conversion program will be used on both Windows and Linux systems and gs seems to be a common denominator. (I'm creating a perl script with a "PS2png" function that will call gs, but I don't think that's relevant to the question.)
I've searched the web and spent a couple of days trying to modify examples I've found, but nothing I have tried does the combination of (a) rotate, (b) resize, (c) maintain the aspect ratio and (d) avoid clipping.
I did find an example that injects a "scale" command into the postscript stream, and that seems to work well to scale the image to the desired size while maintaining the aspect ratio. But I can't find a way to rotate the resized image so that the, e.g., 601 x 792 point (2504 x 3300 pixel) postscript input becomes an 800 x 608 pixel png output.
I'm looking for the ghostscript/postscript fu that I can pass to the gs command line to accomplish this.
I've tried gs command lines with various combinations of -dFIXEDMEDIA, -dFitPage, -dAutoRotatePages=/None, or /All, -c "<> setpagedevice", changing -dDISPLAYWIDTHPOINTS and -dDISPLAYHEIGHTPOINTS, -g[width]x[height], -dUseCropBox with rotated coordinates, and other things I've forgotten. None of those worked, though it wouldn't surprise me if there's a magic combination of some of them that will. I just haven't been able to find it.
Here is the core code that produces the scaled but not rotated output:
## "$molps" is the input ps file read to a variable
## insert the PS "scale" command
$molps = $sf . " " . $sf . " scale\n" . $molps;
$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$molps\" \| $gscmd");
$device_width_points and $device_height_points are calculated by taking the original image size and applying the scaling factor $sf.
I'll be grateful to anyone who can show me the way to accomplish this. Thanks!
Better Answer:
You almost had it with your initial research. Just set orientation in the gs call:
... | gs ... -dAutoRotatePages=/None -c '<</Orientation 3>> setpagedevice' ...
cf. discussion of setpagedevice in the Red Book, and ghostscript docs (just before section 6.2)
Original Answer:
As well as "scale", you need "rotate" and "translate", not necessarily in that order.
Presumably these are single-page PostScript files?
If you know the bounding box of the Postscript, and the dimensions of the png, it is not too arduous to calculate the necessary transformation. It'll be about one line of code. You just need to ensure you inject it in the correct place.
Chapter 6 of the Blue Book has lots of details
A ubc.ca paper provides some illustrated examples (skip to page 4)
Simple PostScript file to play around with. You'll just need the three translate,scale,rotate commands in some order. The rest is for demonstrating what's going on.
%!
% function to define a 400x400 box outline, origin at 0,0 (bottom left)
/box { 0 0 moveto 0 400 lineto 400 400 lineto 400 0 lineto closepath } def
box clip % pretend the box is our bounding box
clippath stroke % draw initial black bounding box
(Helvetica) findfont 50 scalefont setfont % setup a font
% draw box, and show some text # 100,100
box stroke
100 100 moveto (original) show
% try out some transforms
1 0 0 setrgbcolor % red
.5 .5 scale
box stroke
100 100 moveto (+scaled) show
0 1 0 setrgbcolor % green
300 100 translate
box stroke
100 100 moveto (+translated) show
0 0 1 setrgbcolor % blue
45 rotate
box stroke
100 100 moveto (+rotated) show
showpage
It may be possible to insert the calculated transformation into the gs commandline like this:
... | gs ... -c '1 2 scale 3 4 translate 5 6 rotate' -# ...
Thanks to JHNC, I think I have it licked now, and for the benefit of posterity, here's what worked. (Please upvote JHNC, not this answer.)
## code to determine original size, scaling factor, rotation goes above
my $device_width_points;
my $device_height_points;
my $orientation;
if ($rotation) {
$orientation = 3;
$device_width_points = $ytotal_png_pt;
$device_height_points = $xtotal_png_pt;
} else {
$orientation = 0;
$device_width_points = $xtotal_png_pt;
$device_height_points = $ytotal_png_pt;
}
my $orientation_string =
" -dAutoRotatePages=/None -c '<</Orientation " .
$orientation . ">> setpagedevice'";
## $ps = .ps file read into variable
## insert the PS "scale" command
$ps = $sf . " " . $sf . " scale\n" . $ps;
$gsopt1 = " -r300 -dGraphicsAlphaBits=4 -dTextAlphaBits=4";
$gsopt1 = $gsopt1 . " -dDEVICEWIDTHPOINTS=$device_width_points";
$gsopt1 = $gsopt1 . " -dDEVICEHEIGHTPOINTS=$device_height_points";
$gsopt1 = $gsopt1 . " -sOutputFile=" . $outfile;
$gsopt1 = $gsopt1 . $orientation_string;
$gscmd = "gs -q -sDEVICE=pnggray -dNOPAUSE -dBATCH " . $gsopt1 . " - ";
system("echo \"$ps\" \| $gscmd");
One of the problems I had was that some options apparently don't play well together -- for example, I tried using the -g option to set the output size in pixels, but in that case the rotation didn't work. Using the DEVICE...POINTS commands instead did work.

ImageMagick using alpha channel to control calculating min, max and mean image values

ImageMagick command identify prints to screen the min, max and mean values of all the pixels in an image - e.g. for an RGB TIF image we can see the mean thus:
identify -verbose -quiet image.tif | grep mean
which lists (for Red Green Blue and Gray):
mean: 122.974 (0.48225)
mean: 107.722 (0.422438)
mean: 84.1278 (0.329913)
mean: 104.941 (0.411534)
Q: if my image has a boolean alpha channel can I use it to limit the calculations to include only those pixels where alpha was set to 1?
I tried using the clip-mask option with either leading - or + but the means didn't change as would be expected.
In ImageMagick, the -scale 1x1! function can be used to compute the mean without including alpha so that you get the mean of only opaque values. So you could do the following:
Create test transparent image:
convert logo: -transparent white logot.png
Compute mean values:
convert logot.png -scale 1x1! -alpha off -format "%[fx:255*u.r], %[fx:255*u.g], %[fx:255*u.b]" info:
100.202, 81.4747, 98.6342
Alternately, you can use the alpha channel as a mask to get the means. You compute the mean of each channel without the alpha channel and the background under the alpha set to black. Then compute the mean of the alpha channel. Then divide each channel mean by the mean of the alpha channel.
convert logo: -transparent white logot.png
convert logot.png -alpha extract alpha.png
means_rgb=$(convert logot.png -background black -alpha background -alpha off -format "%[fx:mean.r],%[fx:mean.g],%[fx:mean.b]" info:)
mean_r=$(echo $means_rgb | cut -d, -f1)
mean_g=$(echo $means_rgb | cut -d, -f2)
mean_b=$(echo $means_rgb | cut -d, -f3)
mean_alpha=$(convert alpha.png -format "%[fx:mean]" info:)
mean_r=$(convert xc: -format "%[fx:255*$mean_r/$mean_alpha]" info:)
mean_g=$(convert xc: -format "%[fx:255*$mean_g/$mean_alpha]" info:)
mean_b=$(convert xc: -format "%[fx:255*$mean_b/$mean_alpha]" info:)
echo "$mean_r, $mean_g, $mean_b"
100.203, 81.4768, 98.6362
To get the min and max, taking the cue from Mark Setchell's idea:
convert logot.png -background black -alpha background -alpha off -format "%[fx:255*maxima.r], %[fx:255*maxima.g], %[fx:255*maxima.b]\n" info:
255, 250, 244
convert logot.png -background white -alpha background -alpha off -format "%[fx:255*minima.r], %[fx:255*minima.g], %[fx:255*minima.b]\n" info:
4, 0, 0

perl win32 powerpoint setting font color

I need to produce a large number of Powerpoint files with varying text (program of conference sessions). I try to do this with Perl and Win32::OLE. This works well with the exception of setting the color of the text I post. All I can set is the value for Red in RGB, but not the other colors. I use Powerpoint 2010. Also, I can change the color in Powerpoint via VBA.
Here is the code I use (commented with #- are some options that I tried and that did not work).
use strict;
use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft PowerPoint';
$Win32::OLE::Warn = 2; # Throw Errors, I'll catch them
my $PptApp = Win32::OLE->GetActiveObject('PowerPoint.Application')|| Win32::OLE->new('PowerPoint.Application', 'Quit');
$PptApp->{Visible} = 1;
my $Presentation = $PptApp->Presentations->Open({FileName=>'<input-filename.ppt>',ReadOnly=>1});
my $Slide = $Presentation->Slides(1);
$Slide->{Name} = "Slide1";
my $TextBox=$Slide->Shapes->AddTextbox({Orientation=>1,
Left=>25,
Top=>25,
Width=>550,
Height=>50,
});
$TextBox->TextFrame->TextRange->{Text} ="Big Ole Test";
$TextBox->TextFrame->TextRange->Font->{Color} = 255;
#- $TextBox->TextFrame->TextRange->Font->{Color} => ({RGB=>(Red=>86, Green=>55, Blue=>201)});
## Black
#- $TextBox->TextFrame->TextRange->Font->Color->RGB=>[255,255,255];
## Black
#- $TextBox->TextFrame->TextRange->Font->Color => [255,255,255];
## Black
#- $TextBox->TextFrame->TextRange->Font->Color->RGB => 'RGB(255,255,255)';
## Black
#- $TextBox->TextFrame->TextRange->Font->{Color}->{RGB}=>[255,255,255];
## Black
$Presentation ->SaveAs('<output-filename.ppt>');
You have to pass the value of the VBA RGB function. (Source) That's an integral value, not an array of integer values, or a string.
The value of RGB function can be calculated easily with some simple bit manipulation. The calculation for Red (r), Green (g) and Blue (b) components is:
(r) | (g << 8) | (b << 16)
Where | is the bitwise OR operator and << is the left shift operator. If you'd prefer to work without using bitwise operations, you could also use this calculation:
r + (g * 256) + (b * 65536)