Welcome Guest! You need to login or register to make posts.

Notification

Icon
Error

Options
Go to last post Go to first unread
Raymund  
#1 Posted : Friday, December 13, 2019 9:52:23 AM(UTC)
Raymund

Rank: Newbie

Groups: Member
Joined: 10/2/2015(UTC)
Posts: 5

Hi,

I was using the System.Drawing library to create the image sequence of the slideshow video from static images. The following code is the main resize logic. Unfortunately, the performance of the System.Drawing library is very disappointed, especially when I try to make the video to a larger size 1080P

Code:

public void DrawToFile(string filePath, int width, int height)
{
	var dstframeRect = new Rectangle(0, 0, width, height);
	using (var frameBmp = new Bitmap(width, height))
	{
		using (var gFrame = Graphics.FromImage(frameBmp))
		{
			gFrame.Clear(Color.Transparent);
			gFrame.CompositingQuality = CompositingQuality.HighQuality;
			gFrame.CompositingMode = CompositingMode.SourceOver;

			gFrame.InterpolationMode = InterpolationMode.HighQualityBicubic;
			gFrame.SmoothingMode = SmoothingMode.HighQuality;
			gFrame.PixelOffsetMode = PixelOffsetMode.HighQuality;

			foreach (var part in Parts)
			{
				using (var stream = new MemoryStream(part.Scene.Bytes))
				{
					using (var sourceImage = new Bitmap(stream))
					{
						using (var imageAttributes = GetImageAttributesWithAlpha(part.Alpha))
						{
							// part.Rectangle is RectangleF class and contains source floating point rectangle information
							gFrame.DrawImage(sourceImage,
								dstframeRect,
								part.Rectangle.X,
								part.Rectangle.Y,
								part.Rectangle.Width,
								part.Rectangle.Height,
								GraphicsUnit.Pixel,
								imageAttributes,
								null);
						}
					}
				}
			}
		}
		frameBmp.Save(filePath, ImageFormat.Jpeg);
	}
}


Then when I try to convert the above code with GraphicsMill library 9 as below, the performance is mush faster, however there are two problems in the outputs:
1. the generated image sequence is not as smooth as before. I believe this is because the above code gFrame.DrawImage is using RectangleF class which is using float variable. I cannot use RectangleF class in the Aurigma.GraphicsMill.Drawing.Graphics.DrawImage function below and you can see I convert the RectangleF to Rectangle, so the the float variables are converted to int.
2. the resized image is streched. How to control the resize mode in this case

Code:

public void DrawToFile(string filePath, int width, int height)
{
	var dstRect = new Rectangle(0, 0, width, height);
	using (var frameBmp = new Aurigma.GraphicsMill.Bitmap(width, height, PixelFormat.Format32bppArgb))
	{
		using (var gFrame = frameBmp.GetGraphics())
		{
			gFrame.Clear(Color.Transparent);

			foreach (var part in Parts)
			{
				using (var stream = new MemoryStream(part.Scene.Bytes))
				{
					using (var sourceImage = new Aurigma.GraphicsMill.Bitmap(stream))
					{
						var srcRectF = new RectangleF(part.Rectangle.X,
							part.Rectangle.Y,
							part.Rectangle.Width,
							part.Rectangle.Height);
						var srcRect = Rectangle.Truncate(srcRectF);
						if (srcRect.Width == 0)
						{
							// make sure Rectangle is not out of range
							srcRect.Width = 1;
						}

						if (srcRect.Height == 0)
						{
							srcRect.Height = 1;
						}
						
						// the srcRect here is Rectangle class but not RectangleF class
						gFrame.DrawImage(sourceImage, dstRect, srcRect, CombineMode.Alpha, part.Alpha, ResizeInterpolationMode.High);
					}
				}
			}
		}
		frameBmp.Save(filePath, new JpegSettings(95));
	}
}



Please let me know if you have any advice. Many thanks!

Edited by user Friday, December 13, 2019 9:52:59 AM(UTC)  | Reason: Not specified

Eugene Kosmin  
#2 Posted : Monday, December 16, 2019 9:30:54 PM(UTC)
Eugene Kosmin

Rank: Advanced Member

Groups: Member, Administration, Moderator
Joined: 9/19/2006(UTC)
Posts: 462

Was thanked: 29 time(s) in 29 post(s)
Hi,

Sorry for the long delay.

Please try this code:
Code:
static public void DrawToFile(string filePath, int width, int height)
{
	using (var frameBmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
	{
		frameBmp.Fill(RgbColor.Transparent);

		var srcRect = new Rectangle(...);

		using (var ms = new SomeStream())
		using (var srcBitmap = new Bitmap(ms))
		{
			srcBitmap.Transforms.Crop(srcRect);
			srcBitmap.Transforms.Resize(width, height, ResizeInterpolationMode.Anisotropic9, ResizeMode.Fit);

			frameBmp.Draw(srcBitmap, 0, 0, CombineMode.Alpha);
		}
				
		frameBmp.Save(filePath, new JpegSettings(95));
	}
}


You can control resize mode and quality through the parameters of the Resize method. And do not use Graphics - it's an overhead in terms of performance. You don't need it if you are not going to draw some geometry.
Best regards,
Eugene Kosmin
The Aurigma Development Team
Raymund  
#3 Posted : Tuesday, December 17, 2019 2:38:16 PM(UTC)
Raymund

Rank: Newbie

Groups: Member
Joined: 10/2/2015(UTC)
Posts: 5

Eugene,

Thanks for your feedback. This code performs better than my version, and I can control the resize mode now. However, the smoothness problem still exists.

Here are the videos I generated with System.Drawing and GraphicsMill Library

1. Video with System.Drawing: (smoother)
http://vhtbucket-dev.s3....a6-9499-94e12280acbf.mp4

2. Video with GraphicsMill Library: (shaky)
http://vhtbucket-dev.s3....95-98e6-0049f292c9d3.mp4

As I mentioned before, I generate the image sequence based on the individual image. Each frame describes a small and simple movement of each image, like zoom in/zoom out. Because each video frame requires a precise movement change, so I assume this is related to the RectangleF class. With the System.Drawing Library, I was using the float variable to specify the source Rectangle X, Y, Width, and Height. However, with the GraphicsMill library, I cannot crop the rectangle with the float variable.

Let me know if you need any other information, and thanks again.

Code with System.Drawing:
Code:

public void DrawToFile(string filePath, int width, int height)
{
	var dstframeRect = new Rectangle(0, 0, width, height);
	using (var frameBmp = new Bitmap(width, height))
	{
		using (var gFrame = Graphics.FromImage(frameBmp))
		{
			gFrame.Clear(Color.Transparent);
			gFrame.CompositingQuality = CompositingQuality.HighQuality;
			gFrame.CompositingMode = CompositingMode.SourceOver;

			gFrame.InterpolationMode = InterpolationMode.HighQualityBicubic;
			gFrame.SmoothingMode = SmoothingMode.HighQuality;
			gFrame.PixelOffsetMode = PixelOffsetMode.HighQuality;

			foreach (var part in Parts)
			{
				using (var stream = new MemoryStream(part.Scene.Bytes))
				{
					using (var sourceImage = new Bitmap(stream))
					{
						using (var imageAttributes = GetImageAttributesWithAlpha(part.Alpha))
						{
							// part.Rectangle is RectangleF class and contains source floating point rectangle information
							gFrame.DrawImage(sourceImage,
								dstframeRect,
								part.Rectangle.X,
								part.Rectangle.Y,
								part.Rectangle.Width,
								part.Rectangle.Height,
								GraphicsUnit.Pixel,
								imageAttributes,
								null);
						}
					}
				}
			}
		}
		frameBmp.Save(filePath, ImageFormat.Jpeg);
	}
}


Code with GraphicsMill Library:
Code:

 public void DrawToFile(string filePath, int width, int height)
{
	using (var frameBmp = new Aurigma.GraphicsMill.Bitmap(width, height, PixelFormat.Format32bppArgb))
	{
		frameBmp.Fill(RgbColor.Transparent);

		foreach (var part in Parts)
		{
			var srcRectF = new RectangleF(part.Rectangle.X,
				part.Rectangle.Y,
				part.Rectangle.Width,
				part.Rectangle.Height);
			// I need to convert to Rectangle here to use Bitmap.Transforms.Crop, and thus the X, Y, Width, Height become int!
			var srcRect = Rectangle.Round(srcRectF); 

			using (var stream = new MemoryStream(part.Scene.Bytes))
			{
				using (var srcBitmap = new Aurigma.GraphicsMill.Bitmap(stream))
				{
					srcBitmap.Transforms.Crop(srcRect);
					srcBitmap.Transforms.Resize(width, height, ResizeInterpolationMode.High, ResizeMode.Resize);

					frameBmp.Draw(srcBitmap, 0, 0, CombineMode.Alpha, part.Alpha);
				}
			}
		}

		frameBmp.Save(filePath, new JpegSettings(95));
	}
}


If you are interested to see how the video frames look like, I have uploaded them to Dropbox.
1. System.Drawing image sequence:
https://www.dropbox.com/...ZpBeD6Mp_Nb6MoeEtJa?dl=0
2. GraphicsMill Library image sequence:
https://www.dropbox.com/...MClJbgwwHz5IQVpDIBa?dl=0

Edited by user Tuesday, December 17, 2019 2:55:44 PM(UTC)  | Reason: Not specified

Eugene Kosmin  
#4 Posted : Tuesday, December 17, 2019 5:38:35 PM(UTC)
Eugene Kosmin

Rank: Advanced Member

Groups: Member, Administration, Moderator
Joined: 9/19/2006(UTC)
Posts: 462

Was thanked: 29 time(s) in 29 post(s)
Yes, the problem is in floating coordinates. Initially, I thought you have a quality issue because of that.

Unfortunately, our Resize works only with int coordinates, so I don't see how to eliminate the shaking effect of the sequence of frames. I guess it should be some offset parameter for the Resize, which could move the content more precisely.

I'll add it to our bug tracker.
Best regards,
Eugene Kosmin
The Aurigma Development Team
Raymund  
#5 Posted : Wednesday, December 18, 2019 9:11:36 AM(UTC)
Raymund

Rank: Newbie

Groups: Member
Joined: 10/2/2015(UTC)
Posts: 5

Understood. Will Graphics Mill have a plan to fix this shortly, like this month or the next month?

And just curious, when I decompile the DrawImage method in Aurigma.GraphicsMill.Drawing.Graphics class, I do see a DrawOnInternal function accepts floating coordinates. Is there a way to expose that function, or you have any concern about it?

Capture.jpg

Edited by user Wednesday, December 18, 2019 2:47:30 PM(UTC)  | Reason: Not specified

Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.