Dumping a customized LINQPad chart inline - charts

If I don't customize a chart in LINQPad there is a method for dumping inline using linqpadChart.DumpInline().
Is there an similar method for dumping a customized chart inline, or is creating and dumping a Bitmap like I've done in this example the only way?
string[] xSeries = { "John", "Mary", "Sue" };
int[] ySeries = { 100, 120, 140 };
var winChart = xSeries.Chart().AddYSeries (ySeries, Util.SeriesType.Pie).ToWindowsChart();
// Make tweaks/customizations:
var area = winChart.ChartAreas.First();
area.Area3DStyle.Enable3D = true;
area.Area3DStyle.Inclination = 50;
winChart.Series.First().Points[2].SetCustomProperty ("Exploded", "true");
// Draw it to a bitmap and then dump it:
using (var bitmap = new Bitmap(500, 500))
{
winChart.DrawToBitmap(bitmap, new Rectangle(Point.Empty, bitmap.Size));
bitmap.Dump();
}

Yes, this is similar to what DumpInline does behind the scenes, albeit with a WebChart.
Here's the code from LINQPadChart, if you'd like to copy it to My Extensions
public static class MyExtensions
{
public static Bitmap ToBitmap (this Chart chart, int width = 0, int height = 0)
{
if (width <= 0) width = Screen.PrimaryScreen.WorkingArea.Width / 2;
if (height <= 0) height = width / 2;
var img = new Bitmap (width, height);
using (Graphics g = Graphics.FromImage (img))
chart.Printing.PrintPaint (g, new Rectangle (0, 0, width, height));
return img;
}
}
This method requires the following namespaces:
System.Drawing
System.Windows.Forms
System.Windows.Forms.DataVisualization.Charting
Edit: changed the method so that it uses the Windows Forms chart rather than the Web Forms chart, so that it also works in .NET Core.

Related

How to get better video quality using Accord.Video.FFMPEG.DLL

I have developed a Visual Studio Winapp that produces a video file utilizing Accord.Video.FFMPEG.DLL.
The quality the video is less than the original images.
Here is the code and then a sample original image and snapshot of the resulting video.
What can I change to improve the video image?
VideoFileWriter writer = new VideoFileWriter();
writer.Open(outfile, width, height, 1, VideoCodec.Mpeg4);
for (int i = firstrow; i <= testframes; i++)
{
Bitmap bitmap = new Bitmap(ffiles[i, 0].ToString());
writer.WriteVideoFrame(bitmap);
bitmap.Dispose();
}
I tried Bitmap image = new Bitmap(width, height, PixelFormat.Format64bppArgb);
I tried multiple configurations, and it looks like using VP9 codec and WebM file gives the best quality.
We may also set the bitRate argument to high value.
Code sample:
using Accord.Video.FFMPEG;
using Accord.Math;
using System.Drawing;
namespace Testings
{
public class Program
{
static void Main(string[] args)
{
Bitmap tmp_bitmap = new Bitmap(#"Image640x480.png");
int width = tmp_bitmap.Width; //640
int height = tmp_bitmap.Height; //480
tmp_bitmap.Dispose();
VideoFileWriter writer = new VideoFileWriter();
//writer.Open(#"outfile.mp4", width, height, new Rational(1, 1), VideoCodec.H264);
writer.Open(#"outfile.webm", width, height, new Rational(1, 1), VideoCodec.VP9, 50000000);
for (int i = 0; i < 10; i++)
{
Bitmap bitmap = new Bitmap(#"Image640x480.png"); //For the example, I used the same image.
writer.WriteVideoFrame(bitmap);
bitmap.Dispose();
}
writer.Close();
}
}
}
Note:
The output colors doesn't seem accurate, and there are multiple options that doesn't work.
Instead of using Accord, I recommend using FFmpeg CLI, or looking for a better package.

I want to implement the automatic capture function that shows the game view in Unity

I'm using this as a capture.
ScreenCapture.CaptureScreenshot($"Screenshot{_shotIndex}.png", size);
But the CpatureScreenshot() is too slow.
So I tried different scripts but failed. One of them is that I succeeded in capturing the scene view.
public void TakeTransparentScreenshot(Camera cam, int width, int height, string savePath)
{
// Depending on your render pipeline, this may not work.
var bak_cam_targetTexture = cam.targetTexture;
var bak_cam_clearFlags = cam.clearFlags;
var bak_RenderTexture_active = RenderTexture.active;
var tex_transparent = new Texture2D(width, height, TextureFormat.ARGB32, false);
// Must use 24-bit depth buffer to be able to fill background.
var render_texture = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGB32);
var grab_area = new Rect(0, 0, width, height);
RenderTexture.active = render_texture;
cam.targetTexture = render_texture;
cam.clearFlags = CameraClearFlags.SolidColor;
// Simple: use a clear background
cam.backgroundColor = Color.clear;
cam.Render();
tex_transparent.ReadPixels(grab_area, 0, 0);
tex_transparent.Apply();
// Encode the resulting output texture to a byte array then write to the file
byte[] pngShot = ImageConversion.EncodeToPNG(tex_transparent);
File.WriteAllBytes(savePath, pngShot);
cam.clearFlags = bak_cam_clearFlags;
cam.targetTexture = bak_cam_targetTexture;
RenderTexture.active = bak_RenderTexture_active;
RenderTexture.ReleaseTemporary(render_texture);
Texture2D.Destroy(tex_transparent);
}
How do I capture a screenshot in Unity3d with a transparent background?
I need to capture the game view, but this script does the scene view.
Inevitably I tried to implement a feature that was automatically captured using CaptureScreenshot() and Coroutine. it was too slow to work.

Uno platform: load embedded resource file

How do I load an embedded resource for the Android head ? My code, below works for UWP:
Assembly assembly = GetType ().GetTypeInfo ().Assembly;
string[] names = assembly.GetManifestResourceNames ();
Console.WriteLine ("Resource Names");
foreach (var name in names)
Console.WriteLine (" " + name);
using (var stream = assembly.GetManifestResourceStream (Source))
{
bmpSrc = SKBitmap.Decode (stream);
}
And, the XAML is
<controls:ExpandableImage
...
Source="UnoTest.Assets.icons.folder_tab.png"
/>
The file resides in UnoTest.Shared/Assets/ and is marked as "embedded resource".
The debug output shows that one of the "names" is
"UnoTest.Droid.Assets.icons.folder_tab.png"
indicating that my URI should be referring to the Android head.
EDIT
Ultimately, in this experiment, I am intending to paint the left part of the bitmap in the left of the target area, the right in the right, and fill the middle with an expansion of a vertical stripe from the bitmap's mid section. Then, draw some text over it.
private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
...
// identify left, right halves and a 10px wide swath of the middle of the source bitmap
SKRect rectSrcLeft = new SKRect(0, 0, bmpSrc.Width / 2, bmpSrc.Height);
SKRect rectSrcRight = new SKRect(bmpSrc.Width / 2, 0, bmpSrc.Width, bmpSrc.Height);
SKRect rectSrcMid = new SKRect(bmpSrc.Width / 2 - 5, 0, bmpSrc.Width / 2 + 5, bmpSrc.Height);
// create a new bitmap containing a 10 pixel wide swatch from middle of bmpSrc
SKBitmap bmpSrcMid = new SKBitmap(10, bmpSrc.Height);
using (SKCanvas tempCanvas = new SKCanvas(bmpSrcMid))
{
SKRect rectDest = new SKRect(0, 0, rectSrcMid.Width, rectSrcRight.Height);
tempCanvas.DrawBitmap(bmpSrc, rectSrcMid, rectDest);
}
var canvas = e.Surface.Canvas;
using (SKPaint paint = new SKPaint())
{
canvas.Save();
float hDest = canvas.DeviceClipBounds.Height;
float scale = hDest / (float)bmpSrc.Height;
canvas.Scale(scale);
paint.IsAntialias = true;
// determine dest rect for middle section
float rightDest = (float)textBounds.Width / scale; // rightmost point of whole target area
SKRect rectDestMid = new SKRect(rectSrcLeft.Width, 0, rightDest - rectSrcRight.Width, rectSrcRight.Height);
// left part of tab
canvas.DrawBitmap(bmpSrc, rectSrcLeft, rectSrcLeft, paint);
// right part of tab
{
SKRect rectDest = new SKRect(rectDestMid.Right, 0, rightDest, rectSrcRight.Height);
canvas.DrawBitmap(bmpSrc, rectSrcRight, rectDest, paint);
}
// mid part of tab
paint.Shader = SKShader.CreateBitmap(bmpSrcMid,
SKShaderTileMode.Repeat,
SKShaderTileMode.Repeat);
canvas.DrawRect(rectDestMid, paint);
canvas.Restore(); // back to orig scale
}
using (SKPaint paint = new SKPaint { Color = SKColors.Black })
{
float leftText = 20; // matches padding in ListPage.xaml
float bottomText = canvas.DeviceClipBounds.Height / 2 + textCoreHeight / 2;
canvas.DrawText(Label, new SKPoint(leftText, bottomText), paint);
}
}
The XAML for the control is:
<UserControl
x:Class="UnoTest.Shared.Controls.ExpandableImage"
...
<skia:SKXamlCanvas x:Name="EICanvas" PaintSurface="OnPaintSurface" />
</UserControl>
Do I need to write some code to modify the "generic" URI for the Android case ?
Embedded Resources defined in shared projects are sharing the default namespace of the project referencing that shared project, making the file name different in all projects by default in Uno templates.
You have multiple options:
Change the default namespace to be the same in all projects.
Skip the first two dots and use this as the base
Use a different project (a .NET Standard 2.0 project will do) and place your resources there
Here's what I ended up doing. It is not 100% robust but pretty close. And it's really simple.
if (Source == null)
return;
string sourceWithNameSpace = null;
Assembly assembly = GetType ().GetTypeInfo ().Assembly;
string[] names = assembly.GetManifestResourceNames ();
foreach (var name in names)
{
if (name.EndsWith (Source))
{
sourceWithNameSpace = name;
break;
}
}
if (sourceWithNameSpace == null)
return;
using (var stream = assembly.GetManifestResourceStream (sourceWithNameSpace))
{
bmpSrc = SKBitmap.Decode (stream);
}
And, in the XML file, leave off the project head from the Source path, e.g.:
Source="Assets.icons.folder_tab.png"

How target a movieClip in animate cc in this drag drop code

is there a way to modify this code for animate cc to make object in the stage and interact with it ?
it is a bit of pain to make drag and drop in createjs for animate cc
there is nothing in the web that describe how to do it for animate cc or flash cc even the documentation has nothing to tell about drag and drop in the canvas
//Stage
var stage = new createjs.Stage("demoCanvas");
//VARIABLES
//Drag Object Size
dragRadius = 40;
//Destination Size
destHeight = 100;
destWidth = 100;
//Circle Creation
var label = new createjs.Text("DRAG ME", "14px Lato", "#fff");
label.textAlign="center";
label.y -= 7;
var circle = new createjs.Shape();
circle.graphics.setStrokeStyle(2).beginStroke("black")
.beginFill("red").drawCircle(0,0, dragRadius);
//Drag Object Creation
//Placed inside a container to hold both label and shape
var dragger = new createjs.Container();
dragger.x = dragger.y = 100;
dragger.addChild(circle, label);
dragger.setBounds(100, 100, dragRadius*2, dragRadius*2);
//DragRadius * 2 because 2*r = width of the bounding box
var label2 = new createjs.Text("HERE", "bold 14px Lato", "#000");
label2.textAlign = "center";
label2.x += 50;
label2.y += 40;
var box = new createjs.Shape();
box.graphics.setStrokeStyle(2).beginStroke("black").rect(0, 0, destHeight, destWidth);
var destination = new createjs.Container();
destination.x = 350;
destination.y = 50;
destination.setBounds(350, 50, destHeight, destWidth);
destination.addChild(label2, box);
//DRAG FUNCTIONALITY =====================
dragger.on("pressmove", function(evt){
evt.currentTarget.x = evt.stageX;
evt.currentTarget.y = evt.stageY;
stage.update(); //much smoother because it refreshes the screen every pixel movement instead of the FPS set on the Ticker
if(intersect(evt.currentTarget, destination)){
evt.currentTarget.alpha=0.2;
box.graphics.clear();
box.graphics.setStrokeStyle(3)
.beginStroke("#0066A4")
.rect(0, 0, destHeight, destWidth);
}else{
evt.currentTarget.alpha=1;
box.graphics.clear(); box.graphics.setStrokeStyle(2).beginStroke("black").rect(0, 0, destHeight, destWidth);
}
});
//Mouse UP and SNAP====================
dragger.on("pressup", function(evt) {
if(intersect(evt.currentTarget, destination)){
dragger.x = destination.x + destWidth/2;
dragger.y = destination.y + destHeight/2;
dragger.alpha = 1;
box.graphics.clear();
box.graphics.setStrokeStyle(2).beginStroke("black").rect(0, 0, destHeight, destWidth);
stage.update(evt);
}
});
//Tests if two objects are intersecting
//Sees if obj1 passes through the first and last line of its
//bounding box in the x and y sectors
//Utilizes globalToLocal to get the x and y of obj1 in relation
//to obj2
//PRE: Must have bounds set for each object
//Post: Returns true or false
function intersect(obj1, obj2){
var objBounds1 = obj1.getBounds().clone();
var objBounds2 = obj2.getBounds().clone();
var pt = obj1.globalToLocal(objBounds2.x, objBounds2.y);
var h1 = -(objBounds1.height / 2 + objBounds2.height);
var h2 = objBounds2.width / 2;
var w1 = -(objBounds1.width / 2 + objBounds2.width);
var w2 = objBounds2.width / 2;
if(pt.x > w2 || pt.x < w1) return false;
if(pt.y > h2 || pt.y < h1) return false;
return true;
}
//Adds the object into stage
stage.addChild(destination, dragger);
stage.mouseMoveOutside = true;
stage.update();
thanks
I am not exactly sure what you are asking. The demo you showed works fine (looks like it came from this codepen), and it is not clear what you are trying to add. This demo was made directly in code, not with Animate CC - which is really good for building assets, animations, and display list structure, but you should write application code around what gets exported.
There are plenty of documentation and examples online for Drag and Drop, in the EaselJS GitHub, and EaselJS docs:
DragAndDrop demo in GitHub
Live demo on EaselJS demos page
Documentation on pressMove
Tutorial on Mouse Events which includes Drag and Drop
I recommend narrowing down what you are trying to do, show what code or approaches you have tried so far, and posting specific questions here.
Lastly, here is the first part of an ongoing series for working with Animate CC: http://blog.gskinner.com/archives/2015/04/introduction-to-the-flash-cc-html5-canvas-document.html
Cheers.

iTextSharp - Some pages not stamped as expected

I'm using iTextSharp 5.0.6 to read an existing PDF, iterate each page stamping text on each, and then writing out the newly stamped PDF. The issue I'm faced with is that this isn't working 100% of the time. For some PDFs every page is stamped as expected, for others most pages are stamped while some are not. Seems as if there's potentially an issue where the stamper's GetOverContent() is not returning the top-most layer, but that's just an assumption. Has anyone had a similar issue?
using iTextSharp.text;
using iTextSharp.text.pdf;
const string WATERMARK_TEXT = "John Doe";
static void Main(string[] args)
{
string masterPdf = "master.pdf";
string pdfToCreate = "watermark.pdf";
byte[] bytes = StampPDF(masterPdf);
using (FileStream stream = new FileStream(pdfToCreate, FileMode.Create))
{
stream.Write(bytes, 0, bytes.Length);
}
}
static byte[] StampPDF(string PdfPath)
{
using (MemoryStream memoryStream = new MemoryStream())
{
PdfReader reader = new PdfReader(PdfPath);
int pageCount = reader.NumberOfPages;
PdfStamper stamper = new PdfStamper(reader, memoryStream);
float fontSize = 9;
float textAngle = 0f;
BaseFont font = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.WINANSI, BaseFont.EMBEDDED);
BaseColor backgroundColor = new BaseColor(0, 0, 0);
BaseColor fontColor = new BaseColor(255, 255, 255);
float padding = 2f;
float fontWidth = font.GetWidthPoint(WATERMARK_TEXT, fontSize);
iTextSharp.text.Rectangle pageSize;
PdfContentByte pageContents;
for (int i = 1; i <= pageCount; i++)
{
pageSize = reader.GetPageSize(i);
pageContents = stamper.GetOverContent(i);
//draw a rectangle
pageContents.SetColorFill(backgroundColor);
pageContents.MoveTo(pageSize.Width - (fontWidth + padding), 0f);
pageContents.LineTo(pageSize.Width, 0f);
pageContents.LineTo(pageSize.Width, 14f);
pageContents.LineTo(pageSize.Width - (fontWidth + padding), 14f);
pageContents.Fill();
//drop our watermark on top of the rectangle we just created
pageContents.BeginText();
pageContents.SetColorFill(fontColor);
pageContents.SetFontAndSize(font, fontSize);
pageContents.ShowTextAligned(PdfContentByte.ALIGN_LEFT, WATERMARK_TEXT, pageSize.Width - fontWidth, 4, textAngle);
pageContents.EndText();
}
stamper.Close();
reader.Close();
return memoryStream.ToArray();
}
}
For those that may encounter the same problem the key is inspecting the CropBox. Since the dimensions of a PDF's CropBox may be less than that of its PageSize you need to conditionally use one or the other. So, based on the code sample above the for loop would be altered as so:
for (int i = 1; i <= pageCount; i++)
{
mediaBox = reader.GetPageSize(i);
cropBox = reader.GetCropBox(i);
overContent = stamper.GetOverContent(i);
if (cropBox != null && (cropBox.Width < mediaBox.Width || cropBox.Height < cropBox.Height))
mediaBox = cropBox;
//draw a rectangle
overContent.SetColorFill(backgroundColor);
overContent.MoveTo(mediaBox.Right - (fontWidth + fontPadding), mediaBox.Bottom);
overContent.LineTo(mediaBox.Right, mediaBox.Bottom);
overContent.LineTo(mediaBox.Right, mediaBox.Bottom + rectangleHeight);
overContent.LineTo(mediaBox.Right - (fontWidth + fontPadding), mediaBox.Bottom + rectangleHeight);
overContent.ClosePathFillStroke();
//drop our watermark on top of the rectangle we just created
overContent.BeginText();
overContent.SetColorFill(fontColor);
overContent.SetFontAndSize(font, fontSize);
overContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, WATERMARK_TEXT, mediaBox.Right - fontWidth, mediaBox.Bottom + (rectangleHeight - fontSize), textAngle);
overContent.EndText();
}
You've made two mistakes:
You're assuming that the pages aren't rotated, but they can be: 90, 180, 270. Note that I've never seen a 180 page, but its legal. When drawing to a rotated page, you have to take that rotation into account when drawing on it. Fun with transformation matrices.
You're assuming that the page's (unrotated) lower left corner is 0,0. You're basing your measurements on the page's width and height (close), but aren't adjusting for any offset in that bottom left corner.
There are three ways to do a landscape page:
11"x8.5"
8.5"x11" # 90 degrees rotation
8.5"x11" # 270 degrees rotation
Technically, a 4th way is to build an 11x8.5 # 180, but anyone writing such code should be Punished. A lot.
There are various SO questions floating about that give details on how to deal with page rotation. Going by your code, I'd say you'll figure out the llx,lly thing pretty quickly.