Re-size a Placeable Metafile - gdi+

I know that standard WMF file uses an 18-byte header followed by GDI command records. A simple web search tells me that : "There are two additional WMF variations that place another header in front of the standard header. A Placeable Metafile uses a 22-byte header containing x-y coordinates for positioning the image on the page". but I kind of don't understaffed the real life application for such meta file type? What kind of requirements is this type supposed to address in comparison to the standard WMF?
Why am I interested? I have the following code for re-sizing and converting a WMF to GIF which fails at the point it tries to construct the bitmap out of the META file:
public Stream Resize(string filePath, int maxSize)
{
try
{
MemoryStream stream = new MemoryStream();
using (Metafile img = new Metafile(filePath))
{
MetafileHeader header = img.GetMetafileHeader();
float scale = header.DpiX / 96f;
var newSize = CalcaulateSize(img.Width, img.Height, maxSize);
using (Bitmap bitmap = new Bitmap((int)(scale * img.Width / header.DpiX * 100), (int)(scale * img.Height / header.DpiY * 100)))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
g.ScaleTransform(scale, scale);
g.DrawImage(img, 0, 0);
}
var resizedBitmap = new Bitmap(newSize.Width, newSize.Height);
using (var g2 = Graphics.FromImage(resizedBitmap))
{
g2.CompositingQuality = CompositingQuality.HighQuality;
g2.InterpolationMode = InterpolationMode.HighQualityBicubic;
g2.SmoothingMode = SmoothingMode.AntiAlias;
g2.PixelOffsetMode = PixelOffsetMode.HighQuality;
g2.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
g2.TextContrast = 12;
g2.Clear(Color.White);
g2.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height);
}
resizedBitmap.Save(stream, ImageFormat.Gif);
}
stream.Position = 0;
}
return stream;
}
catch (Exception)
{
return null;
}
and raises the exception "Argument is not valid".
(int)(scale * img.Width / header.DpiX * 100) = 22181
(int)(scale * img.Height / header.DpiY * 100)) = 33718
[too much memory to be allocated for a single bitmap all at once which results in immediate exception]
How would you alter the attached code to re-size and convert a place-able meta file?

I'd suspect that your size calculation is off.
Looking at my C++ code, I have this calculation based on the information in the enhanced metafile header where hEMF is the handle of the metafile. We then draw the image using a Graphics directly to the screen using those dimensions.
Hope this or the MSDN link helps a little. Sorry it's not more complete.
ENHMETAHEADER emh;
UINT nBytes = ::GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh);
if (nBytes != 0) {
RECT rect{ // Based on info from http://support.microsoft.com/kb/230675
(int) ((float) (emh.rclFrame.left) * emh.szlDevice.cx / (emh.szlMillimeters.cx*100.0f)), // Left
(int) ((float) (emh.rclFrame.top) * emh.szlDevice.cy / (emh.szlMillimeters.cy*100.0f)), // Top
(int) ((float) (emh.rclFrame.right) * emh.szlDevice.cx / (emh.szlMillimeters.cx*100.0f)), // Right
(int) ((float) (emh.rclFrame.bottom) * emh.szlDevice.cy / (emh.szlMillimeters.cy*100.0f)) // Bottom
};
bounds.x = abs(rect.right - rect.left);
bounds.y = abs(rect.bottom - rect.top);

Related

Circle mask acts like rectangle

I'm trying to draw an object masked with a circle, but the mask applied is more like a circle's bounding rectangle
I tried using circle drawn with drawCircle method:
private function squareToRound(ability:MovieClip):MovieClip
{
var container:MovieClip = new MovieClip();
var newAbility:MovieClip = ability;
var newMask:MovieClip = new MovieClip();
newAbility.width = 43;
newAbility.height = 43;
newMask.x = newAbility.x + newAbility.width / 2;
newMask.y = newAbility.y + newAbility.height / 2;
container.addChild(newAbility);
newMask.graphics.beginFill();
newMask.graphics.drawCircle(0, 0, 8);
newMask.graphics.endFill();
container.addChild(newMask);
newAbility.mask = newMask;
return container;
}
... and as an asset from SWF:
private function squareToRound(ability:MovieClip):MovieClip
{
var container:MovieClip = new MovieClip();
var newAbility:MovieClip = ability;
var newMask:MovieClip = new CircleAbilityMask();
newAbility.width = 43;
newAbility.height = 43;
newMask.x = newAbility.x + newAbility.width / 2;
newMask.y = newAbility.y + newAbility.height / 2;
container.addChild(newAbility);
container.addChild(newMask);
newAbility.mask = newMask;
return container;
}
The results are equal.
I checked what the mask looks like by commenting "newAbility.mask = newMask;" line
This should be resolved in the current OpenFL release:
https://github.com/openfl/openfl/blob/develop/CHANGELOG.md#650-11102017
You can also use Cairo (on native platforms) or Canvas (on HTML5) for smoother/better masking support:
openfl test html5 -Dcanvas
openfl test windows -Dcairo
These are also used when you bitmapData.draw, sprite.cacheAsBitmap = true or other APIs that trigger a software render rather than GL.

Replace GDI+ DrawImage with PInvoked GDI and transparent PNG's

I've created an image service in C# which takes a base layer image (JPG), layers one more more transparent PNG's (32 bit), and then outputs a final JPG image. I'm trying to squeeze every last millisecond out of this function and my code is bottlenecking at the DrawImage call in GDI+. Managed code here:
// Load base image and create graphics
Image image = LoadImage(renderSettings.RenderedImageDirectory + baseLayer);
Graphics graphics = Graphics.FromImage(image);
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
// Draw additional layers to final image
for (int i = 1; i < renderLayers.Count; i++) {
// SLOW -- LoadImage just a utility method that returns an Image from disk or cache
graphics.DrawImage(LoadImage(renderSettings.RenderedImageDirectory + renderLayers[i]), 0, 0, image.Width, image.Height);
}
if (graphics != null) graphics.Dispose();
Now, I read about the performance gains obtained by calling GDI directly by P/Invoke and made an attempt at replacing the DrawImage call. I created a unit test to try to duplicate the same functionality of loading a JPG and then layering one transparent PNG on top of it.
Ref: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/29582142-0068-40dd-bd99-4b3883a76350
Bitmap sourceImage = new Bitmap("c:\\base.jpg");
Bitmap overlayImage = new Bitmap("c:\\layer1.png");
// NOTE: ImageHelper is a utility class containing all the P/Invoke stuff
// Get source image in memory
Graphics sourceImageGraphics = Graphics.FromImage(sourceImage);
IntPtr sourceImageHDC = sourceImageGraphics.GetHdc();
IntPtr sourceImageCDC = ImageHelper.CreateCompatibleDC(sourceImageHDC);
IntPtr sourceImageHandle = sourceImage.GetHbitmap();
ImageHelper.SelectObject(sourceImageCDC, sourceImageHandle);
// Get overlay image in memory
Graphics overlayImageGraphics = Graphics.FromImage(overlayImage);
IntPtr overlayImageHDC = overlayImageGraphics.GetHdc();
IntPtr overlayImageCDC = ImageHelper.CreateCompatibleDC(overlayImageHDC);
IntPtr overlayImageHandle = overlayImage.GetHbitmap();
ImageHelper.SelectObject(overlayImageCDC, overlayImageHandle);
ImageHelper.BitBlt(sourceImageHDC, 0, 0, sourceImage.Width, sourceImage.Height, overlayImageCDC, 0, 0, ImageHelper.TernaryRasterOperations.SRCAND);
ImageHelper.AlphaBlend(sourceImageHDC, 0, 0, sourceImage.Width, sourceImage.Height, overlayImageCDC, 0, 0, sourceImage.Width, sourceImage.Height, new ImageHelper.BLENDFUNCTION(ImageHelper.AC_SRC_OVER, 0, 0xff, ImageHelper.AC_SRC_ALPHA));
// Release source Image memory.
ImageHelper.DeleteDC(sourceImageCDC);
ImageHelper.DeleteObject(sourceImageHandle);
sourceImageGraphics.ReleaseHdc(sourceImageHDC);
sourceImageGraphics.Dispose();
// Release overlay Image memory.
ImageHelper.DeleteDC(overlayImageCDC);
ImageHelper.DeleteObject(overlayImageHandle);
overlayImageGraphics.ReleaseHdc(overlayImageHDC);
overlayImageGraphics.Dispose();
// Save to jpg
sourceImage.Save("c:\\output.jpg", ImageFormat.Jpeg);
But this fails to produce a layered image. Just the PNG without the base JPG. What should I be doing differently? I'm a little out of my league when in comes to straight GDI.
I ended up using SharpDX to access both the WIC and Direct2d API's. The results are impressive to say the least. When compositing with Direct2d I'm seeing increased performance as much as 400-500% over GDI+.
I also tried GDI+ and the Task Parallel Library to break up images into four quandrants and do compositing work in each core. The results weren't nearly as signficant as using SharpDX.
Here's the code I ended up using. The reference to "renderSettings" is just a configuration object. Substitute as needed along with the renderLayer image list.
/* SharpDX */
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.DXGI;
using SharpDX.IO;
using SharpDX.WIC;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using WicBitmap = SharpDX.WIC.Bitmap;
using D2DPixelFormat = SharpDX.Direct2D1.PixelFormat;
using WicPixelFormat = SharpDX.WIC.PixelFormat;
using Rectangle = System.Drawing.Rectangle;
using Bitmap = System.Drawing.Bitmap;
public Image FlattenImageDirect2d()
{
List<string> renderLayers = new List<string>()
{
"image1.jpg", "image1.png", "image2.png", "image3.png", "image4.png", "image5.png", "image6.png", "image7.png"
};
// Base image
string baseLayer = renderLayers[0];
// Create WIC and D2D factories
var wicFactory = new ImagingFactory();
var ddFactory = new SharpDX.Direct2D1.Factory();
// Get image size using WIC
int baseWidth, baseHeight;
using (var wicStream = new WICStream(wicFactory, renderDirectory + baseLayer, NativeFileAccess.Read)) {
var jpegDecoder = new JpegBitmapDecoder(wicFactory);
jpegDecoder.Initialize(wicStream, DecodeOptions.CacheOnDemand);
var frame = jpegDecoder.GetFrame(0);
baseWidth = frame.Size.Width;
baseHeight = frame.Size.Height;
frame.Dispose();
jpegDecoder.Dispose();
}
// Resize image?
bool resizeImage = (baseWidth != renderSettings.RenderWidth) || (baseHeight != renderSettings.RenderHeight);
// Bitmaps and render target settings
var wicBitmap = new WicBitmap(wicFactory, renderSettings.RenderWidth, renderSettings.RenderHeight, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);
var renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new D2DPixelFormat(Format.Unknown, AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);
var wicRenderTarget = new WicRenderTarget(ddFactory, wicBitmap, renderTargetProperties);
// Create bitmap render target used to draw all images to
SharpDX.Direct2D1.BitmapRenderTarget bitmapRenderTarget = new SharpDX.Direct2D1.BitmapRenderTarget(wicRenderTarget, CompatibleRenderTargetOptions.None, new D2DPixelFormat(Format.Unknown, AlphaMode.Premultiplied));
// Draw render layers
for (int i = 0; i < renderLayers.Count; i++) {
// First layer is always a jpeg, all other subsequent layers are png's
ImageFormat imageFormat = (i == 0) ? ImageFormat.Jpeg : ImageFormat.Png;
using (SharpDX.WIC.BitmapSource bitmapSource = LoadWicBitmap(wicFactory, renderDirectory + renderLayers[i], imageFormat, resizeImage, renderSettings.RenderWidth, renderSettings.RenderHeight)) {
// Convert WIC pixel format to D2D1 format
var formatConverter = new FormatConverter(wicFactory);
formatConverter.Initialize(bitmapSource, SharpDX.WIC.PixelFormat.Format32bppPBGRA, BitmapDitherType.None, null, 0f, BitmapPaletteType.MedianCut);
// Create direct 2d bitmap from wic bitmap
SharpDX.Direct2D1.Bitmap direct2DBitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(bitmapRenderTarget, formatConverter);
// Draw direct2d image to bitmap render target
wicRenderTarget.BeginDraw();
wicRenderTarget.DrawBitmap(direct2DBitmap, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);
wicRenderTarget.EndDraw();
// Clean up
formatConverter.Dispose();
direct2DBitmap.Dispose();
}
}
// Final image data
byte[] imageData;
// Create streams to write output to.
using (var memoryStream = new MemoryStream()) {
using (var wicStream = new WICStream(wicFactory, memoryStream)) {
// Encode wic bitmap
var encoder = new JpegBitmapEncoder(wicFactory);
encoder.Initialize(wicStream);
var frameEncoder = new BitmapFrameEncode(encoder);
frameEncoder.Initialize();
frameEncoder.SetSize(renderSettings.RenderWidth, renderSettings.RenderHeight);
frameEncoder.PixelFormat = WicPixelFormat.FormatDontCare;
frameEncoder.WriteSource(wicBitmap);
frameEncoder.Commit();
encoder.Commit();
// Set image data
memoryStream.Position = 0;
imageData = memoryStream.ToArray();
// Clean up
frameEncoder.Dispose();
encoder.Dispose();
wicBitmap.Dispose();
wicRenderTarget.Dispose();
bitmapRenderTarget.Dispose();
ddFactory.Dispose();
wicFactory.Dispose();
frameEncoder = null;
encoder = null;
wicBitmap = null;
wicRenderTarget = null;
bitmapRenderTarget = null;
ddFactory = null;
wicFactory = null;
}
}
return Image.FromStream(new MemoryStream(imageData));
}
private BitmapSource LoadWicBitmap(ImagingFactory wicFactory, string path, ImageFormat imageFormat, bool resize, int resizeWidth = 0, int resizeHeight = 0)
{
PngBitmapDecoder pngDecoder;
JpegBitmapDecoder jpegDecoder;
BitmapFrameDecode bitmapFrameDecode;
var stream = new WICStream(wicFactory, path, NativeFileAccess.Read);
// Load the appropriate decoder
if (imageFormat == ImageFormat.Jpeg) {
jpegDecoder = new JpegBitmapDecoder(wicFactory);
jpegDecoder.Initialize(stream, DecodeOptions.CacheOnLoad);
bitmapFrameDecode = jpegDecoder.GetFrame(0);
jpegDecoder.Dispose();
}
else {
pngDecoder = new PngBitmapDecoder(wicFactory);
pngDecoder.Initialize(stream, DecodeOptions.CacheOnDemand);
bitmapFrameDecode = pngDecoder.GetFrame(0);
pngDecoder.Dispose();
}
// Clean up
stream.Dispose();
// Resize if necessary
if (resize) {
// Prepare scaler
var scaler = new BitmapScaler(wicFactory);
scaler.Initialize(bitmapFrameDecode, resizeWidth, resizeHeight, SharpDX.WIC.BitmapInterpolationMode.Fant);
return (BitmapSource)scaler;
}
return (BitmapSource)bitmapFrameDecode;
}
This one should work:
private Bitmap GetImage() {
//##################### Get the Bitmaps ############################
Bitmap sourceImage = new Bitmap("c:\\1.png");
Bitmap overlayImage = new Bitmap("c:\\2.png");
//##################### Get Hdc from baselayer ############################
Graphics sourceImageGraphics = Graphics.FromImage(sourceImage);
IntPtr sourceImageHDC = sourceImageGraphics.GetHdc();
//##################### Get Cdc from second layer ############################
IntPtr overlayImageCDC = CreateCompatibleDC(sourceImageHDC);
IntPtr overlayImageHandle = overlayImage.GetHbitmap();
SelectObject(overlayImageCDC, overlayImageHandle);
/*
* BitBlt from sourceImage is not neccessary,
* because Graphics.FromImage(sourceImage) already did it for you
*/
//##################### Draw the second layer ############################
AlphaBlend(sourceImageHDC, 0, 0, overlayImage.Width, overlayImage.Height, overlayImageCDC, 0, 0, overlayImage.Width, overlayImage.Height, new BLENDFUNCTION(AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA));
//##################### Release everthing ############################
sourceImageGraphics.ReleaseHdc(sourceImageHDC);
sourceImageGraphics.Dispose();
DeleteDC(overlayImageCDC);
DeleteObject(overlayImageHandle);
//##################### Return Image ############################
return sourceImage;
}

Actionscript/Air/Flex 4 - Load Image from File, Scale Down, and Save as PNG

I wrote these functions which I use in conjunction to scale down some BitmapData and save it as a PNG. However, the scaledImage.draw(originalImage, scalingMatrix, null, null, null, true); line with smoothing set to true does not have the intended smoothing effect when I save the bitmap data as a PNG using the second function. The resulting image file is not antialiased at all. Is there anything I'm doing wrong here? Thanks!
public static function scaleImage(originalImage:BitmapData, size:int):BitmapData
{
// Calculate the scaled size.
var scale:Number;
var scaledWidth:Number;
var scaledHeight:Number;
if (originalImage.width > originalImage.height)
{
scale = (size as Number) / (originalImage.width as Number);
scaledWidth = size;
scaledHeight = originalImage.height * scale;
}
else
{
scale = (size as Number) / (originalImage.height as Number);
scaledHeight = size;
scaledWidth = originalImage.width * scale;
}
var scalingMatrix:Matrix = new Matrix();
scalingMatrix.scale(scale, scale);
// Scale the image.
var scaledImage:BitmapData = new BitmapData(scaledWidth, scaledHeight, true, 0x00000000);
scaledImage.draw(originalImage, scalingMatrix, null, null, null, true);
return scaledImage;
}
public static function saveImageAsPNG(image:BitmapData, imageFile:File):void
{
// Encode the image as a PNG.
var pngEncoder:PNGEncoder = new PNGEncoder();
var imageByteArray:ByteArray = pngEncoder.encode(image);
// Write the image data to a file.
var imageFileStream:FileStream = new FileStream();
imageFileStream.open(imageFile, FileMode.WRITE);
imageFileStream.writeBytes(imageByteArray);
imageFileStream.close();
}
Turns out this code was working. It was saving smoothed images. It wasn't apparent because the images I was scaling down were ~20K x 20K pixels so jaggies appeared anyway with smoothing. Smoothing was apparent with more "normal" sized images like 2K x 2K pixels

please help me with image.GetThumbnailImage (it create very low quality image)

i use this code to create thumbnails
System.Drawing.Image.GetThumbnailImageAbort abort = new System.Drawing.Image.GetThumbnailImageAbort(this.ThumbnailCallback);
System.Drawing.Image image2 = image.GetThumbnailImage((int)Math.Round((double)wid / difference), (int)Math.Round((double)hei / difference), abort, IntPtr.Zero);
image2.Save(str2, System.Drawing.Imaging.ImageFormat.Jpeg);
image2.Dispose();
but i get this very low quality image
but it is suposed to be like this one
what i am making wrong
or how can achieve this
Your problem is not really with the GetThumbnailImage() method, but instead in how you are saving the file. You need to specify the quality level of the JPEG you are saving, or it seems it always defaults to a very low value.
Consider this code as a guide (it's from an old .NET 2.0 project; the code still works fine compiled against 4.0, but there may be a more direct method in 4.0; I've never had reason to check)
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpegEncoder = null;
for (int x = 0; x < encoders.Length; x++) {
if (string.Compare(encoders[x].MimeType, "image/jpeg", true) == 0) {
jpegEncoder = encoders[x];
break;
}
}
if (jpegEncoder == null) throw new ApplicationException("Could not find JPEG encoder!");
EncoderParameters prms = new EncoderParameters(1);
prms.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
bitmap.Save(fileName, jpegEncoder, prms);
Here is another solution that should always work without fetching out the encoder. It resizes keeping relation between width & heigh ... modify for your needs.
/// <summary>
/// Resize an image with high quality
/// </summary>
public static Image ResizeImage(Image srcImage, int width)
{
var b = new Bitmap(width, srcImage.Height * width / srcImage.Width);
using (var g = Graphics.FromImage((Image)b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(srcImage, 0, 0, b.Width, b.Height);
}
return b;
}

Adapt asp.net code to resize image

After searching, I've discovered this code:
Public Sub ResizeImage(ByVal scaleFactor As Double, ByVal fromStream As Stream, ByVal toStream As Stream)
Dim image__1 = System.Drawing.Image.FromStream(fromStream)
Dim newWidth = CInt(image__1.Width * scaleFactor)
Dim newHeight = CInt(image__1.Height * scaleFactor)
Dim thumbnailBitmap = New System.Drawing.Bitmap(newWidth, newHeight)
Dim thumbnailGraph = System.Drawing.Graphics.FromImage(thumbnailBitmap)
thumbnailGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality
thumbnailGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
thumbnailGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
Dim imageRectangle = New System.Drawing.Rectangle(0, 0, newWidth, newHeight)
thumbnailGraph.DrawImage(image__1, imageRectangle)
thumbnailBitmap.Save(toStream, image__1.RawFormat)
thumbnailGraph.Dispose()
thumbnailBitmap.Dispose()
image__1.Dispose()
End Sub
There are 2 things I can't "modify" to solve my problem:
I wouldn't like to pass a stream, but I prefer to pass a path like C:\mysite\photo\myphoto.gif. How can I "convert" it to accept a file and not a stream?
In this function I've to pass a "scale" value. But I prefer to check if the image is too big (for example > 1024x768) than resize it to a max of 1024x768. How can I check this with System.Drawing.
As you can see I don't know anything about System.Drawing so I need an "hard" help to solve this job.
Here is some c# code I did about 5 years ago to do this (it should still work I hope as the app hasn't been touched since). I think it does everthing you need but it doesn't upscale the image to 1024x768 if it is smaller. This code will only make sure that if it is larger than 1024x768, it will resize proportionally to fit within those dimensions:
const int maxWidth = 1024;
const int maxHeight = 768;
Image newImage = Image.FromFile("YourPicture.jpg");
double percentToShrink = -1;
if (newImage.Width >= newImage.Height)
{
// Do we need to resize based on width?
if (newImage.Width > maxWidth)
{
percentToShrink = (double)maxWidth / (double)newImage.Width;
}
}
else
{
// Do we need to resize based on width?
if (newImage.Height > maxHeight )
{
percentToShrink = (double)maxHeight / (double)newImage.Height;
}
}
int newWidth = newImage.Width;
int newHeight = newImage.Height;
// So do we need to resize?
if (percentToShrink != -1)
{
newWidth = (int)(newImage.Width * percentToShrink);
newHeight = (int)(newImage.Height * percentToShrink);
}
// convert the image to a png and get a byte[]
MemoryStream imgStream = new MemoryStream();
Bitmap bmp = new Bitmap(newWidth, newHeight);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(System.Drawing.Brushes.White, 0, 0, newWidth, newHeight);
g.DrawImage(newImage, 0, 0, newWidth, newHeight);
}
// This can be whatever format you need
bmp.Save(imgStream, System.Drawing.Imaging.ImageFormat.Png);
byte[] imgBinaryData = imgStream.ToArray();
imgStream.Dispose();
If you need to convert this to VB.NET, you can use the C# to VB.NET converter here.
First question:
Dim newImage As Image = Image.FromFile("SampImag.jpg")
Second question:
Build a private method that will return you a Size object based on the original Size object of the given image. You can add a "keep proportions" flag also if you wish.

Resources