SetResolution does nothing when joining tiff images - c#

I've been trying to adjust the resolution for a new tiff that gets created from a group of other tiffs. I would like to drop the resolution to 100x100 dpi. Everything with the join works properly but the resolution in the final tiff will always be what the resolution is of the files I am joining together (used 300x300 dpi images). I have tried using some suggestions (Set DPI value to Tiff Image in C#) for getting/setting the PropertyItems but that has failed as well. Using the join technique below, what would be the proper way to set the resolution of the final image to 100x100 dpi?
Thank you.
public byte[] JoinTiffImages(
List<byte[]> images)
{
var fPage = FrameDimension.Page;
var nearest =
System.Drawing
.Drawing2D
.InterpolationMode
.NearestNeighbor;
if (images.Count == 0)
{
throw new ImageConverterException(
"Could not join an empty set of images.");
}
else if (images.Count == 1)
{
return images[0];
}
else
{
using (var ms = new MemoryStream())
{
using (var masterBitmap =
(Bitmap)DrawingImage.FromStream(
new MemoryStream(images[0])))
{
//get the codec for tiff files
var info = GetTifCodecInfo();
var enc = Encoder.SaveFlag;
var ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(
enc,
(long)EncoderValue.MultiFrame);
ep.Param[1] = new EncoderParameter(
Encoder.Compression,
(long)TifCompression.ToEncoderValue());
masterBitmap.SetResolution(100.0f, 100.0f);
masterBitmap.Save(ms, info, ep);
//save the intermediate frames
ep.Param[0] = new EncoderParameter(
enc,
(long)EncoderValue.FrameDimensionPage);
for (int i = 1; i < images.Count; i++)
{
using (var nextImg = (Bitmap)DrawingImage.FromStream(
new MemoryStream(images[i])))
{
for (int x = 0;
x < nextImg.GetFrameCount(fPage);
x++)
{
nextImg.SetResolution(100.0f, 100.0f);
nextImg.SelectActiveFrame(fPage, x);
masterBitmap.SaveAdd(nextImg, ep);
}
}
}
ep.Param[0] =
new EncoderParameter(
enc,
(long)EncoderValue.Flush);
//close out the file.
masterBitmap.SaveAdd(ep);
return ms.ToArray();
}
}
}
}

Here is a code that creates a multi-page tif file from a list of images.
It sets the DPI both to the master and all parts according to an input paramter.
private void saveTiff_Click(List<Image> imgList, string saveName, int dpi)
{
//all kudos to : http://bobpowell.net/generating_multipage_tiffs.aspx
foreach (Image img in imgList) ((Bitmap)img).SetResolution(dpi, dpi);
System.Drawing.Imaging.Encoder enc = System.Drawing.Imaging.Encoder.SaveFlag;
Bitmap master = new Bitmap(imgList[0]);
master.SetResolution(dpi, dpi);
ImageCodecInfo info = null;
// lets hope we have an TIF encoder
foreach (ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders())
if (ice.MimeType == "image/tiff") info = ice;
// one parameter: MultiFrame
EncoderParameters ep = new EncoderParameters(1);
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);
master.Save(saveName, info, ep);
// one parameter: further frames
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
for (int i = 1; i < imgList.Count; i++) master.SaveAdd(imgList[i], ep);
// one parameter: flush
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
master.SaveAdd(ep);
}

I was able to resolve my issue with some help from the comments. This function will handle the resolution change without the image changing size.
public static byte[] JoinTiffImages(
List<byte[]> images,
float res)
{
var fPage = FrameDimension.Page;
var nearest =
System.Drawing
.Drawing2D
.InterpolationMode
.NearestNeighbor;
if (images.Count == 0)
{
throw new Exception(
"Could not join an empty set of images.");
}
else if (images.Count == 1)
{
return images[0];
}
else
{
var ms = new MemoryStream();
//get the codec for tiff files
var info = GetTifCodecInfo();
var ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag,
(long)EncoderValue.MultiFrame);
ep.Param[1] = new EncoderParameter(
System.Drawing.Imaging.Encoder.Compression,
(long)EncoderValue.CompressionLZW);
using (var masterImg =
(Bitmap)System.Drawing.Image.FromStream(
new MemoryStream(images[0])))
{
using (var resizedMaster =
new Bitmap(
(int)(masterImg.Width *
(res /
masterImg.HorizontalResolution)),
(int)(masterImg.Height *
(res /
masterImg.VerticalResolution))))
{
resizedMaster.SetResolution(
res,
res);
using (var gr = Graphics.FromImage(resizedMaster))
{
gr.InterpolationMode = nearest;
gr.DrawImage(
masterImg,
new Rectangle(
0,
0,
resizedMaster.Width,
resizedMaster.Height),
0,
0,
masterImg.Width,
masterImg.Height,
GraphicsUnit.Pixel);
}
resizedMaster.Save(ms, info, ep);
//save the intermediate frames
ep.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag,
(long)EncoderValue.FrameDimensionPage);
for (int i = 1; i < images.Count; i++)
{
using (var nextImg =
(Bitmap)System.Drawing.Image.FromStream(
new MemoryStream(images[i])))
{
for (int x = 0;
x < nextImg.GetFrameCount(fPage);
x++)
{
nextImg.SelectActiveFrame(fPage, x);
using (var resizedNext =
new Bitmap(
(int)(nextImg.Width *
(res /
nextImg.HorizontalResolution)),
(int)(nextImg.Height *
(res /
nextImg.VerticalResolution))))
{
resizedNext.SetResolution(
res,
res);
using (var gr =
Graphics.FromImage(resizedNext))
{
gr.InterpolationMode = nearest;
gr.DrawImage(
nextImg,
new Rectangle(
0,
0,
resizedNext.Width,
resizedNext.Height),
0,
0,
nextImg.Width,
nextImg.Height,
GraphicsUnit.Pixel);
}
resizedMaster.SaveAdd(resizedNext, ep);
}
}
}
}
ep.Param[0] =
new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag,
(long)EncoderValue.Flush);
//close out the file.
resizedMaster.SaveAdd(ep);
}
return ms.ToArray();
}
}
}
private static ImageCodecInfo GetTifCodecInfo()
{
foreach (var ice in ImageCodecInfo.GetImageEncoders())
{
if (ice.MimeType == "image/tiff")
{
return ice;
}
}
return null;
}

Related

Use SharpDX to capture screenshot of rotated monitor

The code below successfully takes screenshots of the monitors attached to my Windows 10 laptop computer, so long as the monitors are not "flipped". When the monitors are flipped to any orientation except "landscape" the captured images are all black pixels (r,g,b,a = 0,0,0,255)
How can I modify the code below so that it will also work with flipped monitors?
Target Framework is:
Net 4.8
Referenced packages are:
SharpDX 4.2.0
SharpDX.Direct2D1 4.2.0
SharpDX.Direct3D11 4.2.0
SharpDX.DXGI 4.2.0
SharpDX.DXGI 4.2.0
using System;
using System.IO;
using System.Runtime.ExceptionServices;
using SharpDX;
namespace ScreenCast {
internal static class Program {
[STAThread]
private static void Main() {
var captureCount = 0;
using var factory = new SharpDX.DXGI.Factory4();
foreach (var adapter in factory.Adapters1) {
using var device = new SharpDX.Direct3D11.Device(adapter);
foreach (var output in adapter.Outputs) {
if (output.Description.IsAttachedToDesktop) {
var description = output.Description;
using var output1 = output.QueryInterface<SharpDX.DXGI.Output1>();
Capture($"{captureCount++}.bmp", device, output1);
}
output.Dispose();
}
adapter.Dispose();
}
}
private static void Capture(string outputFileName, SharpDX.Direct3D11.Device device, SharpDX.DXGI.Output1 output1) {
int width = output1.Description.DesktopBounds.Right - output1.Description.DesktopBounds.Left;
int height = output1.Description.DesktopBounds.Bottom - output1.Description.DesktopBounds.Top;
using var stagingScreenTexture = new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription {
Width = width,
Height = height,
CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read,
BindFlags = SharpDX.Direct3D11.BindFlags.None,
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = SharpDX.Direct3D11.ResourceUsage.Staging
});
using var duplicatedOutput = output1.DuplicateOutput(device);
SharpDX.DXGI.Resource screenResource = null;
SharpDX.DXGI.OutputDuplicateFrameInformation duplicateFrameInformation;
AcquireFrame(duplicatedOutput, out duplicateFrameInformation, out screenResource);
duplicatedOutput.ReleaseFrame();
AcquireFrame(duplicatedOutput, out duplicateFrameInformation, out screenResource);
// copy resource into memory that can be accessed by the CPU
using var screenTexture = screenResource.QueryInterface<SharpDX.Direct3D11.Texture2D>();
device.ImmediateContext.CopyResource(screenTexture, stagingScreenTexture);
// Get the desktop capture texture
var mapSource = device.ImmediateContext.MapSubresource(stagingScreenTexture, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
using var bmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var bmpBounds = new System.Drawing.Rectangle(0, 0, width, height);
var bmpData = bmp.LockBits(bmpBounds, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
var src = mapSource.DataPointer;
var dest = bmpData.Scan0;
for (var y = 0; y < height; y++) {
SharpDX.Utilities.CopyMemory(dest, src, width * 4);
src += mapSource.RowPitch;
dest += bmpData.Stride;
}
bmp.UnlockBits(bmpData);
bmp.Save(outputFileName);
device.ImmediateContext.UnmapSubresource(stagingScreenTexture, 0);
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
// Display the texture using system associated viewer
System.Diagnostics.Process.Start(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, outputFileName)));
}
static void AcquireFrame(SharpDX.DXGI.OutputDuplication duplication, out SharpDX.DXGI.OutputDuplicateFrameInformation info, out SharpDX.DXGI.Resource resource) {
while (true) {
try {
duplication.AcquireNextFrame(100, out info, out resource);
return;
} catch (SharpDXException x) {
if (x.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
ExceptionDispatchInfo.Capture(x).Throw();
}
}
}
}
}
First, I only used SharpDX for a few days, so I'm by no means an expert, but I ran into a similar problem when capturing from rotated monitor and from what I've been able to deduce captured frame is not rotated.
e.g. Your monitor is rotated 90 deg to portrait (Width x Height 1080x1920) so you'd expect the captured frame to be portrait as well, right? Nope, you get the 1920 x 1080 landscape bitmap so your screen width= bitmap height and vice versa:
Here is the code I used in my capture class, still work in progress:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using Device = SharpDX.Direct3D11.Device;
using MapFlags = SharpDX.Direct3D11.MapFlags;
namespace EXM.ExampleCapture
{
public class DXScreenCaptureUtil {
private static ImageCodecInfo jpegCodec = ImageCodecInfo.GetImageEncoders()
.First(c => c.FormatID == ImageFormat.Jpeg.Guid);
private static EncoderParameters jpegParams = new EncoderParameters() { Param = new[] { new EncoderParameter(Encoder.Quality, 60L) } };
//Cache objects
private static Factory1 factory = new Factory1();
private static Adapter adapter;
private static Device device;
/// <summary>
/// Gets target device (Display) based on the rectangle we want to capture
/// </summary>
/// <param name="sourceRect">Rectangle we want to capture</param>
/// <returns>Screen which contains the area we want to capture or null if no device contains our area of interest</returns>
private static Screen GetTargetScreen(Rectangle sourceRect) {
foreach (var scr in Screen.AllScreens)
{
if (sourceRect.X >= scr.Bounds.X && sourceRect.Y >= scr.Bounds.Y
&& sourceRect.Right <= scr.Bounds.Width + scr.Bounds.X
&& sourceRect.Bottom <= scr.Bounds.Height + scr.Bounds.Y
)
{
return scr;
}
}
return null;
}
public static (byte[], int) Capture(Rectangle sourceRect, int jpegQuality) {
Screen targetScreen = GetTargetScreen(sourceRect);
if (targetScreen == null) {
throw new Exception($#"Could not find target screen for capture rectangle {sourceRect}");
}
//This is to instruct client receiving the image to rotate it, seems like a reasonable thing to offload it to client and save a bit of CPU time on server
int rotation = 0;
byte[] imageBytes = null;
// Width/Height of desktop to capture
int width = targetScreen.Bounds.Width;
int height = targetScreen.Bounds.Height;
Rectangle cropRect = new Rectangle(sourceRect.X - targetScreen.Bounds.X, sourceRect.Y - targetScreen.Bounds.Y, sourceRect.Width, sourceRect.Height);
// Create DXGI Factory1
if (adapter == null) { adapter = factory.Adapters.Where(x => x.Outputs.Any(o => o.Description.DeviceName == targetScreen.DeviceName)).FirstOrDefault(); }
// Create device from Adapter
if (device == null) { device = new Device(adapter); }
//using (var output = adapter.Outputs.Where(o => o.Description.DeviceName == targetScreen.DeviceName).FirstOrDefault()) //This creates a memory leak!
Output output = null;
//I'm open to suggestions here:
for (int i = 0; i < adapter.GetOutputCount(); i++) {
output = adapter.GetOutput(i);
if (output.Description.DeviceName == targetScreen.DeviceName) {
break;
}
else {
output.Dispose();
}
}
using (var output1 = output.QueryInterface<Output1>()) {
if (output1.Description.Rotation == DisplayModeRotation.Rotate90) {
width = targetScreen.Bounds.Height;
height = targetScreen.Bounds.Width;
int offsetX = targetScreen.Bounds.X - sourceRect.X;
cropRect = new Rectangle(
sourceRect.Y - targetScreen.Bounds.Y,
targetScreen.Bounds.Width - (sourceRect.Width + offsetX),
sourceRect.Height, sourceRect.Width);
rotation = 90;
}
else if (output1.Description.Rotation == DisplayModeRotation.Rotate270) {
width = targetScreen.Bounds.Height;
height = targetScreen.Bounds.Width;
int offsetY = targetScreen.Bounds.Y - sourceRect.Y;
cropRect = new Rectangle(
targetScreen.Bounds.Height - (sourceRect.Height + offsetY),
targetScreen.Bounds.X - sourceRect.X,
sourceRect.Height, sourceRect.Width);
rotation = 270;
}
else if (output1.Description.Rotation == DisplayModeRotation.Rotate180) {
rotation = 180;
}
// Create Staging texture CPU-accessible
var textureDesc = new Texture2DDescription {
CpuAccessFlags = CpuAccessFlags.Read,
BindFlags = BindFlags.None,
Format = Format.B8G8R8A8_UNorm,
Width = width,
Height = height,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = ResourceUsage.Staging
};
using (var screenTexture = new Texture2D(device, textureDesc))
//Duplicate the output
using (var duplicatedOutput = output1.DuplicateOutput(device)) {
bool captureDone = false;
SharpDX.DXGI.Resource screenResource = null;
OutputDuplicateFrameInformation duplicateFrameInformation;
for (int i = 0; !captureDone; i++) {
try {
//Try to get duplicated frame within given time
duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out screenResource);
//Ignore first call, this always seems to return a black frame
if (i == 0) {
screenResource.Dispose();
continue;
}
//copy resource into memory that can be accessed by the CPU
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>()) {
device.ImmediateContext.CopyResource(screenTexture2D, screenTexture);
}
//Get the desktop capture texture
var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None);
var boundsRect = new System.Drawing.Rectangle(0, 0, width, height);
//Create Drawing.Bitmap
using (var bitmap = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb)) {
//Copy pixels from screen capture Texture to GDI bitmap
var bitmapData = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
var sourcePtr = mapSource.DataPointer;
var destinationPtr = bitmapData.Scan0;
for (int y = 0; y < height; y++) {
//Copy a single line
Utilities.CopyMemory(destinationPtr, sourcePtr, width * 4);
//Advance pointers
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
destinationPtr = IntPtr.Add(destinationPtr, bitmapData.Stride);
}
//Release source and dest locks
bitmap.UnlockBits(bitmapData);
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
//Save the output
imageBytes = CropBitmapToJPEGBytes(bitmap, cropRect, jpegQuality);
}
//Capture done
captureDone = true;
}
catch (SharpDXException e) {
if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) {
throw;
}
}
finally {
//Dispose manually
if (screenResource != null) {
screenResource.Dispose();
}
duplicatedOutput.ReleaseFrame();
}
}
}
}
output.Dispose();
return (imageBytes, rotation);
}
/// <summary>
/// Crop bitmap
/// </summary>
/// <param name="orig">Original bitmap</param>
/// <param name="cropRect">Crop rectangle</param>
/// <returns>Cropped bitmap</returns>
static byte[] CropBitmapToJPEGBytes(Bitmap orig, Rectangle cropRect, int jpegQuality) {
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, (long)jpegQuality);
jpegParams.Param[0] = qualityParam;
byte[] imageBytes;
using (Bitmap nb = new Bitmap(cropRect.Width, cropRect.Height)) {
using (Graphics g = Graphics.FromImage(nb)) {
g.DrawImage(orig, -cropRect.X, -cropRect.Y);
using (MemoryStream s = new MemoryStream()) {
nb.Save(s, jpegCodec, jpegParams);
imageBytes = s.ToArray();
}
}
}
return imageBytes;
}
}
}

Final image has smaller image after merging multiple images

I am trying to create a big final jpg image from 4 different jpg images. I noticed after adding images onto the final image, the size of the image changes.
The size of the image should remain the same on the final image too.
Ex- The galaxy image(dark sky) on the final image looks small, compared to the actual image.
Any help would be appreciated.
private void CombineImages()
{
string path1 = #"C:\temp\";
DirectoryInfo directory = new DirectoryInfo(path1);
//change the location to store the final image.
FileInfo[] files = directory.GetFiles();
string finalImage = #"C:\\images\\FinalImage3.jpg";
List<int> imageHeights = new List<int>();
List<int> imagewidths = new List<int>();
int nIndex = 0;
int width = 0;
int maxHeight = 0;
int totalHeight = 0;
bool odd = true;
bool firstRow = true;
//to get height and width to create final image
foreach (FileInfo file in files)
{
if (odd)
{
if (firstRow)
{
Image img = Image.FromFile(file.FullName);
firstRow = false;
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
odd = false;
}
else
{
Image img = Image.FromFile(file.FullName);
maxHeight = imageHeights.Max();
imagewidths.Add(width+100);
width = 0;
totalHeight = totalHeight + maxHeight+img.Height+100;
imageHeights.Clear();
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
odd = false;
}
}
else
{
Image img = Image.FromFile(file.FullName);
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
odd = true;
}
}
imageHeights.Sort();
Bitmap img3 = new Bitmap(imagewidths.Max(), totalHeight);
Graphics g = Graphics.FromImage(img3);
g.Clear(Color.Gainsboro);
imageHeights = new List<int>();
imagewidths = new List<int>();
nIndex = 0;
width = 0;
maxHeight = 0;
totalHeight = 0;
odd = true;
firstRow = true;
int imagewidth = 0;
//actual merging of images
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (odd)
{
if (firstRow)
{
g.DrawImage(img, 25, 25);
firstRow = false;
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
odd = false;
}
else
{
maxHeight = imageHeights.Max();
g.DrawImage(img, 25, maxHeight+50);
imagewidths.Add(width);
width = 0;
totalHeight = totalHeight + maxHeight + img.Height;
imageHeights.Clear();
imageHeights.Add(img.Height);
width += img.Width;
imagewidth = img.Width;
img.Dispose();
odd = false;
}
}
else
{
imageHeights.Add(img.Height);
g.DrawImage(img, width+50, maxHeight+50);
img.Dispose();
odd = true;
}
img.Dispose();
}
g.Dispose();
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
img3.Save(finalImage, jpgEncoder, myEncoderParameters);
img3.Dispose();
}
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}

TIFF compression

I am trying to compress some TIFF files. These are in a certain map structure, and so they should stay. With the code bellow, I am able to convert every first file (named 1.tiff) in every subdirectory, but it gives me a System.ArgumentException when there are more than one file in a subdirectory, or if the name of the file is not 1.tiff.
using RasterEdge.Imaging.Basic;
using RasterEdge.XDoc.TIFF;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace LZWCompression
{
class Program
{
static int temp = 0;
static void Main(string[] args)
{
string root = #"C:x\y\";
string path = "z";
Console.WriteLine(Directory.Exists(root + path));
if (Directory.Exists(root + path))
{
// This path is a directory
ProcessDirectory(root + path, root);
Console.WriteLine(root + path);
}
Console.WriteLine("DONE");
Console.ReadKey();
}
// Process all files in the directory passed in, recurse on any directories
// that are found, and process the files they contain.
public static void ProcessDirectory(string targetDirectory, string targetPath)
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(targetDirectory);
foreach (string fileName in fileEntries)
{
Console.WriteLine(fileName);
ProcessFile(fileName, targetPath);
}
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach (string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory, targetPath);
}
public static void ProcessFile(string path, string root)
{
string filename = "";
string location = "";
temp++;
List<Bitmap> images = new List<Bitmap>();
int posFilename = path.LastIndexOf("\\") + 1;
int posRoot = root.Length;
filename = path.Substring(posFilename, path.Length - posFilename);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(800, 1000);
Graphics g = Graphics.FromImage(bitmap);
posFilename = posFilename - (posRoot + 1);
location = path.Substring(posRoot, posFilename);
Bitmap myBitmap;
myBitmap = new Bitmap(filename);
ImageCodecInfo myImageCodecInfo;
myImageCodecInfo = GetEncoderInfo(filename);
System.Drawing.Imaging.Encoder myEncoder;
myEncoder = System.Drawing.Imaging.Encoder.Compression;
EncoderParameters myEncoderParameters;
myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter;
myEncoderParameter = new EncoderParameter(myEncoder, (long)EncoderValue.CompressionLZW);
myEncoderParameters.Param[0] = myEncoderParameter;
myBitmap.Save(path, ImageFormat.Tiff);
Console.WriteLine("myBitmap: " + myBitmap.ToString());
Bitmap bm = (Bitmap)Bitmap.FromFile(path);
bm = ChangeColor(bm);
images.Add(bm);
TIFFDocument doc = new TIFFDocument(images.ToArray(), ImageCompress.LZW);
if (null == doc)
throw new Exception("Fail to construct TIFF Document");
doc.Save(path);
}
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
public static Bitmap ChangeColor(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
//get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
ImageAttributes attributes = new ImageAttributes();
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
//dispose the Graphics object
g.Dispose();
return newBitmap;
}
}
}

Image upload quality bad

I have an application that uploads images to a database and then show them in a webpage by using a Handler. My problem is that the images are showing in a different quality and color than the original ones. I don't know what the problem is.
File = FileUpload1.PostedFile;
imgbin = new Byte[File.ContentLength];
File.InputStream.Read(imgbin, 0, File.ContentLength);
imagename = FileUpload1.FileName;
// Here the image size is defined --------------------
System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream);
UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
UploadedImageHeight = UploadedImage.PhysicalDimension.Height;
//Resize Image
int compressWidth;
if (UploadedImageWidth >639)
{
compressWidth = 640;
}
else
{
compressWidth = Convert.ToInt32(UploadedImageWidth);
}
ResizeImage compressPicture = new ResizeImage();
imgbin = compressPicture.ResizeImageFile(imgbin, compressWidth);
System.Drawing.Image Image = System.Drawing.Image.FromStream(new MemoryStream(imgbin));
public class ResizeImage
{
public byte[] ResizeImageFile(byte[] imageFile, int targetSize) // Set targetSize to 1024
{
using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
{
Size newSize = CalculateDimensions(oldImage.Size, targetSize);
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format64bppPArgb))
{
byte[] byteArray = new byte[0];
using (Graphics canvas = Graphics.FromImage(newImage))
{
canvas.Clear(Color.White);
canvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
canvas.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
canvas.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
int quality = 100;
ImageCodecInfo codec = RetrieveCodec("image/jpeg");
using (MemoryStream m = new MemoryStream())
{
using (EncoderParameters codeParams = new EncoderParameters())
{
using (EncoderParameter p = new EncoderParameter(Encoder.Quality, quality))
{
codeParams.Param[0] = p;
newImage.Save(m, codec, codeParams);
byteArray = m.ToArray();
}
}
}
return byteArray;
}
}
}
}
private ImageCodecInfo RetrieveCodec(string mimeType)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == mimeType)
return codec;
}
return null;
}
public static Size CalculateDimensions(Size oldSize, int targetSize)
{
decimal ajusteTamaño;
Size newSize = new Size();
if (oldSize.Width > targetSize)
{
ajusteTamaño = oldSize.Width / Convert.ToDecimal(targetSize);
newSize.Width = (int)(oldSize.Width / ajusteTamaño);
newSize.Height = (int)(oldSize.Height / ajusteTamaño);
}
else
{
newSize.Width = oldSize.Width;
newSize.Height = oldSize.Height;
}
return newSize;
}
}

create fixed size thumbnail dynamically on listview control

how to create fixed size thumbnail dynamically and resize image in listview best fit the size of the thumbnail.
private void Treeview1_AfterSelect(System.Object sender, System.Windows.Forms.TreeViewEventArgs e)
{
if (folder != null && System.IO.Directory.Exists(folder))
{
try
{
DirectoryInfo dir = new DirectoryInfo(#folder);
foreach (FileInfo file in dir.GetFiles())
{
try
{
imageList.ImageSize = new Size(136, 136);
imageList.ColorDepth = ColorDepth.Depth32Bit;
Image img = new Bitmap(Image.FromFile(file.FullName));
Graphics g = Graphics.FromImage(img);
g.DrawRectangle(Pens.Red, 0, 0, img.Width - 21, img.Height - 21);
//g.DrawRectangle(Pens.Red, 0, 0, img.Width, img.Height);
imageList.Images.Add(img);
}
catch
{
Console.WriteLine("This is not an image file");
}
}
for (int j = 0; j < imageList.Images.Count; j++)
{
this.ListView1.Items.Add("Item" + j);
this.ListView1.Items[j].ImageIndex = j;
}
this.ListView1.View = View.LargeIcon;
this.ListView1.LargeImageList = imageList;
//this.ListView1.DrawItem += new DrawListViewItemEventHandler(ListView1_DrawItem);
//import(folder);
}
catch (Exception ex)
{
}
}
I have code in this answer specifically for resizing images along with resolution:
public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath,
string sOrgFileName,string sThumbNailFileName,
ImageFormat oFormat, int rez)
{
try
{
System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);
decimal pixtosubstract = 0;
decimal percentage;
//default
Size ThumbNailSizeToUse = new Size();
if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
{
if (oImg.Size.Width > oImg.Size.Height)
{
percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
pixtosubstract = percentage * oImg.Size.Height;
ThumbNailSizeToUse.Width = ThumbNailSize.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
}
else
{
percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
pixtosubstract = percentage * (decimal)oImg.Size.Width;
ThumbNailSizeToUse.Height = ThumbNailSize.Height;
ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
}
}
else
{
ThumbNailSizeToUse.Width = oImg.Size.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height;
}
Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
bmp.SetResolution(rez, rez);
System.Drawing.Image oThumbNail = bmp;
bmp = null;
Graphics oGraphic = Graphics.FromImage(oThumbNail);
oGraphic.CompositingQuality = CompositingQuality.HighQuality;
oGraphic.SmoothingMode = SmoothingMode.HighQuality;
oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
oGraphic.DrawImage(oImg, oRectangle);
oThumbNail.Save(sPhysicalPath + sThumbNailFileName, oFormat);
oImg.Dispose();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}

Categories