Saving a generated thumbnail gives Object reference not set exception - c#

How do I save a generated thumbnail? I am getting this error:
Object reference not set to an instance of an object
This is my code. I am new to C#. I found the thumbnail generation code online and I thought I could use it but its giving me an error...
//1. <lcFilename> as path of large size file.
//2. <lnWidth> as width of required thumbnail.
//3. <lnHeight> as height of required thumbnail.
//The function returns a Bitmap object of the changed thumbnail image which you can save on the disk.
public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight)
{
System.Drawing.Bitmap bmpOut = null;
try
{
Bitmap loBMP = new Bitmap(lcFilename);
ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio;
int lnNewWidth = 0;
int lnNewHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)
return loBMP;
if (loBMP.Width > loBMP.Height)
{
lnRatio = (decimal)lnWidth / loBMP.Width;
lnNewWidth = lnWidth;
decimal lnTemp = loBMP.Height * lnRatio;
lnNewHeight = (int)lnTemp;
}
else
{
lnRatio = (decimal)lnHeight / loBMP.Height;
lnNewHeight = lnHeight;
decimal lnTemp = loBMP.Width * lnRatio;
lnNewWidth = (int)lnTemp;
}
bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
loBMP.Dispose();
}
catch
{
return null;
}
return bmpOut;
}
// Thumbnail Generate
string largefilepath = "images/" + imageuploaded;
string largefilepath2 = "images/users/" + imageuploaded + "-160x160";
Bitmap bmp1 = new Bitmap(CreateThumbnail(largefilepath, 160, 160));
bmp1.Save(largefilepath2);

You have to Dispose your Graphics after it finishes its job. When you draw something on an image with Graphics, it is common to use using block but since it is already in the try/catch scope, it seems redundant here.
//1. <lcFilename> as path of large size file.
//2. <lnWidth> as width of required thumbnail.
//3. <lnHeight> as height of required thumbnail.
//The function returns a Bitmap object of the changed thumbnail image which you can save on the disk.
public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight)
{
System.Drawing.Bitmap bmpOut = null;
try
{
Bitmap loBMP = new Bitmap(lcFilename);
ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio;
int lnNewWidth = 0;
int lnNewHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)
return loBMP;
if (loBMP.Width > loBMP.Height)
{
lnRatio = (decimal)lnWidth / loBMP.Width;
lnNewWidth = lnWidth;
decimal lnTemp = loBMP.Height * lnRatio;
lnNewHeight = (int)lnTemp;
}
else
{
lnRatio = (decimal)lnHeight / loBMP.Height;
lnNewHeight = lnHeight;
decimal lnTemp = loBMP.Width * lnRatio;
lnNewWidth = (int)lnTemp;
}
bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
// Dispose Graphics so that it releases all the resources it's holding to draw on that image.
g.Dispose();
/* or you could use Graphics as below.. but it seems redundant, because it is already in the try / catch block.
using ( Graphics g = Graphics.FromImage(bmpOut))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
}
*/
loBMP.Dispose();
}
catch
{
return null;
}
return bmpOut;
}
// Thumbnail Generate
string largefilepath = "images/" + imageuploaded;
string largefilepath2 = "images/users/" + imageuploaded + "-160x160";
Bitmap bmp1 = new Bitmap(CreateThumbnail(largefilepath, 160, 160));
bmp1.Save(largefilepath2);

The problem is you have a try..catch inside your method and this is swallowing the exception, and you are returning null from there, Hence the exception that you have reported.
Option 1
My suggestion is to either do something with the exception such as log it, this way you know something went wrong, like now. And handle the instance where a null value can be returned by the method, as follows:
string largefilepath = "images/" + imageuploaded;
string largefilepath2 = "images/users/" + imageuploaded + "-160x160";
Bitmap bmp1 = new Bitmap(CreateThumbnail(largefilepath, 160, 160));
if (bmp1 == null) {
// there was an exception, check the logs
}
else {
bmp1.Save(largefilepath2);
}
Option 2:
Or remove the try catch completely from the method and move it out as follows:
Note: the following code assumes you have removed the try...catch from the CreateThumbnail method.
try {
//Where imageUploaded is the name of the image with the extension, e.g. "samplePic.jpg"
string largefilepath = #"c:\images\" + imageuploaded;
string largefilepath2 = #"c:\images\users\" + System.IO.Path.GetFileNameWithoutExtension(imageuploaded) + "-160x160" + System.IO.Path.GetExtension(largefilepath);
Bitmap bmp1 = new Bitmap(CreateThumbnail(largefilepath, 160, 160));
bmp1.Save(largefilepath2);
}
catch (Exception ex) {
//do something with the exception
}

Related

How to compress images before storing them in asp.net?

This is my add image code.
protected void SubmitButton_Click(object sender, EventArgs e)
{
ProductImages productImage = new ProductImages();
productImage.ProductID = Convert.ToInt32(ProductDropDownList.SelectedValue.ToString());
if (!FileUpload1.HasFile)
{
MessageLabel1.Text = "Please Select Image File"; //checking if file uploader has no file selected
}
else
{
int length = FileUpload1.PostedFile.ContentLength;
productImage.ProductImage = new byte[length];
FileUpload1.PostedFile.InputStream.Read(productImage.ProductImage, 0, length);
try
{
ProductImageBL.AddProductImages(productImage);
MessageLabel1.Text = "Product Image has been successfully added!";
}
catch (Exception ex)
{
MessageLabel1.Text = "Some error occured while processing the request. Error Description <br/>" + ex.Message;
}
}
}
Image compression depends on image type and what is on image. Photos of real life objects are typically in .jpg and you can't compress them much without noticeable quality losing.
Probably what you really want to do - is resize image to smaller size like 500*500 if you know this will be enought for all your needs. Keep in mind to save image aspect ratio during resizing.
Related SO question:
Resize an Image C#
The SO link posted by dlxeon is excellent. I use the examples there myself.
However all those examples resize the image, but you can also increase the compression in jpeg files and\or decrease the DPI.
Below a complete example of how to resize and compress a jpeg. It also checks if the image needs rotating in case the phone was held vertical for example. And you can add padding if you want to make the image square.
Note that if you use this example as is the transparency of .png and .gif files will be lost because they are converted to jpg.
protected void SubmitButton_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile == true)
{
using (Bitmap postedImage = new Bitmap(FileUpload1.PostedFile.InputStream))
{
byte [] bin = Common.scaleImage(postedImage, 400, 400, false);
Image1.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(bin);
}
}
}
public static byte[] scaleImage(Image image, int maxWidth, int maxHeight, bool padImage)
{
try
{
int newWidth;
int newHeight;
byte[] returnArray;
//check if the image needs rotating (eg phone held vertical when taking a picture for example)
foreach (var prop in image.PropertyItems)
{
if (prop.Id == 0x0112)
{
int rotateValue = image.GetPropertyItem(prop.Id).Value[0];
RotateFlipType flipType = getRotateFlipType(rotateValue);
image.RotateFlip(flipType);
break;
}
}
//apply padding if needed
if (padImage == true)
{
image = applyPaddingToImage(image);
}
//check if the with or height of the image exceeds the maximum specified, if so calculate the new dimensions
if (image.Width > maxWidth || image.Height > maxHeight)
{
var ratioX = (double)maxWidth / image.Width;
var ratioY = (double)maxHeight / image.Height;
var ratio = Math.Min(ratioX, ratioY);
newWidth = (int)(image.Width * ratio);
newHeight = (int)(image.Height * ratio);
}
else
{
newWidth = image.Width;
newHeight = image.Height;
}
//start with a new image
var newImage = new Bitmap(newWidth, newHeight);
//set the new resolution, 72 is usually good enough for displaying images on monitors
newImage.SetResolution(72, 72);
//or use the original resolution
//newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
//resize the image
using (var graphics = Graphics.FromImage(newImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(image, 0, 0, newWidth, newHeight);
}
image = newImage;
//save the image to a memorystream to apply the compression level, higher compression = better quality = bigger images
using (MemoryStream ms = new MemoryStream())
{
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 80L);
image.Save(ms, getEncoderInfo("image/jpeg"), encoderParameters);
//save the stream as byte array
returnArray = ms.ToArray();
}
//cleanup
image.Dispose();
newImage.Dispose();
return returnArray;
}
catch (Exception ex)
{
//there was an error: ex.Message
return null;
}
}
private static ImageCodecInfo getEncoderInfo(string mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType.ToLower() == mimeType.ToLower())
return encoders[j];
}
return null;
}
private static Image applyPaddingToImage(Image image)
{
//get the maximum size of the image dimensions
int maxSize = Math.Max(image.Height, image.Width);
Size squareSize = new Size(maxSize, maxSize);
//create a new square image
Bitmap squareImage = new Bitmap(squareSize.Width, squareSize.Height);
using (Graphics graphics = Graphics.FromImage(squareImage))
{
//fill the new square with a color
graphics.FillRectangle(Brushes.Red, 0, 0, squareSize.Width, squareSize.Height);
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
//put the original image on top of the new square
graphics.DrawImage(image, (squareSize.Width / 2) - (image.Width / 2), (squareSize.Height / 2) - (image.Height / 2), image.Width, image.Height);
}
return squareImage;
}
private static RotateFlipType getRotateFlipType(int rotateValue)
{
RotateFlipType flipType = RotateFlipType.RotateNoneFlipNone;
switch (rotateValue)
{
case 1:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
case 2:
flipType = RotateFlipType.RotateNoneFlipX;
break;
case 3:
flipType = RotateFlipType.Rotate180FlipNone;
break;
case 4:
flipType = RotateFlipType.Rotate180FlipX;
break;
case 5:
flipType = RotateFlipType.Rotate90FlipX;
break;
case 6:
flipType = RotateFlipType.Rotate90FlipNone;
break;
case 7:
flipType = RotateFlipType.Rotate270FlipX;
break;
case 8:
flipType = RotateFlipType.Rotate270FlipNone;
break;
default:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
}
return flipType;
}

How to convert TIF to Black-and-White Monochrome TIF

I would like to use Magick.NET
https://magick.codeplex.com/wikipage?title=Convert%20image&referringTitle=Documentation
in order to convert TIF to Black-and-White Monochrome TIF but manual does not explain it well.
I have tried this code but I am not sure of this approach is a correct one.
using (MagickImage image = new MagickImage("input.tif"))
{
image.CompressionMethod = CompressionMethod.Group4;
image.Write("output.tif");
}
Help needed. Thank you!
I found .NET code to do the same thing without any issues.
http://www.codeproject.com/Articles/15186/Bitonal-TIFF-Image-Converter-for-NET
private void convert_Click(object sender, EventArgs e)
{
// Load a bitmap from disk
Bitmap originalBitmap = new Bitmap(#"..\..\Bitonal-In.tif");
// Display image
originalImage.Image = originalBitmap;
// Convert bitmap to RGB format for drawing
Bitmap rgbBitmap = Converter.ConvertToRGB(originalBitmap);
// Convert image to bitonal for saving to file
Bitmap bitonalBitmap = Converter.ConvertToBitonal(rgbBitmap);
// Display converted image
convertedImage.Image = bitonalBitmap;
// Get an ImageCodecInfo object that represents the TIFF codec.
ImageCodecInfo imageCodecInfo = GetEncoderInfo("image/tiff");
System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.Compression;
EncoderParameters encoderParameters = new EncoderParameters(1);
// Save the bitmap as a TIFF file with group IV compression.
EncoderParameter encoderParameter = new EncoderParameter(encoder, (long)EncoderValue.CompressionCCITT4);
encoderParameters.Param[0] = encoderParameter;
bitonalBitmap.Save(#"..\..\Bitonal-Out.tif", imageCodecInfo, encoderParameters);
}
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace BitonalConverter
{
public static class Converter
{
public static Bitmap ConvertToRGB(Bitmap original)
{
Bitmap newImage = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
newImage.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (Graphics g = Graphics.FromImage(newImage))
{
g.DrawImageUnscaled(original, 0, 0);
}
return newImage;
}
public static Bitmap ConvertToBitonal(Bitmap original)
{
Bitmap source = null;
// If original bitmap is not already in 32 BPP, ARGB format, then convert
if (original.PixelFormat != PixelFormat.Format32bppArgb)
{
source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (Graphics g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0);
}
}
else
{
source = original;
}
// Lock source bitmap in memory
BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Copy image data to binary array
int imageSize = sourceData.Stride * sourceData.Height;
byte[] sourceBuffer = new byte[imageSize];
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
// Unlock source bitmap
source.UnlockBits(sourceData);
// Create destination bitmap
Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
destination.SetResolution(original.HorizontalResolution, original.VerticalResolution);
// Lock destination bitmap in memory
BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// Create destination buffer
imageSize = destinationData.Stride * destinationData.Height;
byte[] destinationBuffer = new byte[imageSize];
int sourceIndex = 0;
int destinationIndex = 0;
int pixelTotal = 0;
byte destinationValue = 0;
int pixelValue = 128;
int height = source.Height;
int width = source.Width;
int threshold = 500;
// Iterate lines
for (int y = 0; y < height; y++)
{
sourceIndex = y * sourceData.Stride;
destinationIndex = y * destinationData.Stride;
destinationValue = 0;
pixelValue = 128;
// Iterate pixels
for (int x = 0; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values) - Thanks murx
// B G R
pixelTotal = sourceBuffer[sourceIndex] + sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2];
if (pixelTotal > threshold)
{
destinationValue += (byte)pixelValue;
}
if (pixelValue == 1)
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = 0;
pixelValue = 128;
}
else
{
pixelValue >>= 1;
}
sourceIndex += 4;
}
if (pixelValue != 128)
{
destinationBuffer[destinationIndex] = destinationValue;
}
}
// Copy binary image data to destination bitmap
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
// Unlock destination bitmap
destination.UnlockBits(destinationData);
// Dispose of source if not originally supplied bitmap
if (source != original)
{
source.Dispose();
}
// Return
return destination;
}
}
}

C# graphics.drawImage() crops my Image

I am trying to put an image on a bigger image. But the inner image was cropped after drawImage(). Here is my code:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
int sizeX = im.Width;
int sizeY = im.Height;
int size = 0;
bool isWidth = false;
if (sizeX > sizeY)
{
size = sizeX; isWidth = true;
}
else if(sizeY > sizeX)
{
size = sizeY; isWidth = false;
}
filename = filename + "New";
Bitmap bg = new Bitmap(size,size);
SolidBrush brush = new SolidBrush(Color.Aqua);
using (Graphics g = Graphics.FromImage(bg))
{
g.FillRectangle(brush, 0, 0, size, size);
if (isWidth==true)
{
g.DrawImage(im, 0, (size - sizeY) / 2);
}
else if(isWidth==false)
{
g.DrawImage(im, (size-sizeX)/2, 0);
}
}
Thanks in advance
My guess would be the resolution of the image is the issue:
Try it like this:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
im.SetResolution(96F, 96F);

Compress/Thumbnail Image after uploading file in c# .net

I want that suppose user upload 2 MB image then from that image i want to generate 1 thumbnail image.
To reduce its size , so i can get speed in loading.
as my listing page contains many images.so i am getting to much loading time.
SO can you tell me how can i compress image or get Thumbnail image???
You can do something like this:
public static Bitmap CreateThumbnail(string filename, int width, int height)
{
Bitmap bmpOut = null;
try
{
Bitmap loBMP = new Bitmap(filename);
ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio;
int lnNewWidth = 0;
int lnNewHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (loBMP.Width < width && loBMP.Height < height)
return loBMP;
if (loBMP.Width > loBMP.Height)
{
lnRatio = (decimal)width / loBMP.Width;
lnNewWidth = width;
decimal lnTemp = loBMP.Height * lnRatio;
lnNewHeight = (int)lnTemp;
}
else
{
lnRatio = (decimal)height / loBMP.Height;
lnNewHeight = height;
decimal lnTemp = loBMP.Width * lnRatio;
lnNewWidth = (int)lnTemp;
}
bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
loBMP.Dispose();
}
catch
{
return null;
}
return bmpOut;
}
Is only a prototype but you can use it for your project

convert bitonal TIFF to bitonal PNG in C#

I need to convert bitonal (black and white) TIFF files into another format for display by a web browser, currently we're using JPGs, but the format isn't crucial. From reading around .NET doesn't seem to easily support writing bitonal images, so we're ending up with ~1MB files instead of ~100K ones. I'm considering using ImageMagick to do this, but ideally i'd like a solution which doesn't require this if possible.
Current code snippet (which also does some resizing on the image):
using (Image img = Image.FromFile(imageName))
{
using (Bitmap resized = new Bitmap(resizedWidth, resizedHeight)
{
using (Graphics g = Graphics.FromImage(resized))
{
g.DrawImage(img, new Rectangle(0, 0, resized.Width, resized.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
}
resized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
Is there any way to achieve this?
Thanks.
I believe the problem can be solved by checking that resized bitmap is of PixelFormat.Format1bppIndexed. If it's not, you should convert it to 1bpp bitmap and after that you can save it as black and white png without problems.
In other words, you should use following code instead of resized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Jpeg);
if (resized.PixelFormat != PixelFormat.Format1bppIndexed)
{
using (Bitmap bmp = convertToBitonal(resized))
bmp.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Png);
}
else
{
resized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Png);
}
I use following code for convertToBitonal :
private static Bitmap convertToBitonal(Bitmap original)
{
int sourceStride;
byte[] sourceBuffer = extractBytes(original, out sourceStride);
// Create destination bitmap
Bitmap destination = new Bitmap(original.Width, original.Height,
PixelFormat.Format1bppIndexed);
destination.SetResolution(original.HorizontalResolution, original.VerticalResolution);
// Lock destination bitmap in memory
BitmapData destinationData = destination.LockBits(
new Rectangle(0, 0, destination.Width, destination.Height),
ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// Create buffer for destination bitmap bits
int imageSize = destinationData.Stride * destinationData.Height;
byte[] destinationBuffer = new byte[imageSize];
int sourceIndex = 0;
int destinationIndex = 0;
int pixelTotal = 0;
byte destinationValue = 0;
int pixelValue = 128;
int height = destination.Height;
int width = destination.Width;
int threshold = 500;
for (int y = 0; y < height; y++)
{
sourceIndex = y * sourceStride;
destinationIndex = y * destinationData.Stride;
destinationValue = 0;
pixelValue = 128;
for (int x = 0; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values)
pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] +
sourceBuffer[sourceIndex + 3];
if (pixelTotal > threshold)
destinationValue += (byte)pixelValue;
if (pixelValue == 1)
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = 0;
pixelValue = 128;
}
else
{
pixelValue >>= 1;
}
sourceIndex += 4;
}
if (pixelValue != 128)
destinationBuffer[destinationIndex] = destinationValue;
}
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
destination.UnlockBits(destinationData);
return destination;
}
private static byte[] extractBytes(Bitmap original, out int stride)
{
Bitmap source = null;
try
{
// If original bitmap is not already in 32 BPP, ARGB format, then convert
if (original.PixelFormat != PixelFormat.Format32bppArgb)
{
source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (Graphics g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0);
}
}
else
{
source = original;
}
// Lock source bitmap in memory
BitmapData sourceData = source.LockBits(
new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Copy image data to binary array
int imageSize = sourceData.Stride * sourceData.Height;
byte[] sourceBuffer = new byte[imageSize];
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
// Unlock source bitmap
source.UnlockBits(sourceData);
stride = sourceData.Stride;
return sourceBuffer;
}
finally
{
if (source != original)
source.Dispose();
}
}
Have you tried saving using the Image.Save overload with Encoder parameters?
Like the Encoder.ColorDepth Parameter?
Trying jaroslav's suggestion for color depth doesn't work:
static void Main(string[] args)
{
var list = ImageCodecInfo.GetImageDecoders();
var jpegEncoder = list[1]; // i know this is the jpeg encoder by inspection
Bitmap bitmap = new Bitmap(500, 500);
Graphics g = Graphics.FromImage(bitmap);
g.DrawRectangle(new Pen(Color.Red), 10, 10, 300, 300);
var encoderParams = new EncoderParameters();
encoderParams.Param[0] = new EncoderParameter(Encoder.ColorDepth, 2);
bitmap.Save(#"c:\newbitmap.jpeg", jpegEncoder, encoderParams);
}
The jpeg is still a full color jpeg.
I don't think there is any support for grayscale jpeg in gdi plus. Have you tried looking in windows imaging component?
http://www.microsoft.com/downloads/details.aspx?FamilyID=8e011506-6307-445b-b950-215def45ddd8&displaylang=en
code example: http://www.codeproject.com/KB/GDI-plus/windows_imaging.aspx
wikipedia: http://en.wikipedia.org/wiki/Windows_Imaging_Component
This is an old thread. However, I'll add my 2 cents.
I use AForge.Net libraries (open source)
use these dlls. Aforge.dll, AForge.Imaging.dll
using AForge.Imaging.Filters;
private void ConvertBitmap()
{
markedBitmap = Grayscale.CommonAlgorithms.RMY.Apply(markedBitmap);
ApplyFilter(new FloydSteinbergDithering());
}
private void ApplyFilter(IFilter filter)
{
// apply filter
convertedBitmap = filter.Apply(markedBitmap);
}
Have you tried PNG with 1 bit color depth?
To achieve a size similar to a CCITT4 TIFF, I believe your image needs to use a 1-bit indexed pallette.
However, you can't use the Graphics object in .NET to draw on an indexed image.
You will probably have to use LockBits to manipulate each pixel.
See Bob Powell's excellent article.

Categories