Thursday, August 20, 2009

How to compress, resize image in .net (C#, VB, Asp.net)

You may want to compress image and save to a new file or compress them while loading any big images in your asp.net application.

Here you go:

Asp.net with C#

//Suppose we get image from query string
string strImgUrl = Request.QueryString["imgUrl"];
//Load image
System.Drawing.Image imgFullSize = System.Drawing.Image.FromFile(strImgUrl);
//Set return image type
Response.ContentType = "image/gif";
//Create Encoder Parameter and specify the quality
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality,50L);
// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;

//Resize image if you want
//In this case, if the image width greater than 1800, do resize width and height
//int intWidth, intHeight;
//intWidth = imgFullSize.Width;
//intHeight = imgFullSize.Height;
//if (imgFullSize.Width > 1800)
//{
//intWidth = 1800;
//intHeight = (int)(((float)intWidth / imgFullSize.Width) * imgFullSize.Height);
//}

//System.Drawing.Image imgThumbNail = imgFullSize.GetThumbnailImage(intWidth, //intHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), //IntPtr.Zero);
//imgThumbNail.Save(Response.OutputStream, jpegCodec, encoderParams);
//imgThumbNail.Dispose();

//Return image
imgFullSize.Save(Response.OutputStream, jpegCodec, encoderParams);



C#

private void VaryQualityLevel()
{
// Get a bitmap.
Bitmap bmp1 = new Bitmap(@"c:\TestPhoto.jpg");

//Or you do can use buil-in method
//ImageCodecInfo jgpEncoder GetEncoderInfo("image/gif");//"image/jpeg",...
ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;

// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);

EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityFifty.jpg", jgpEncoder, myEncoderParameters);

myEncoderParameter = new EncoderParameter(myEncoder, 100L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityHundred.jpg", jgpEncoder, myEncoderParameters);

// Save the bitmap as a JPG file with zero quality level compression.
myEncoderParameter = new EncoderParameter(myEncoder, 0L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(@"c:\TestPhotoQualityZero.jpg", jgpEncoder, myEncoderParameters);

}


...


private ImageCodecInfo GetEncoder(ImageFormat format)
{

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}



VB.net


Private Sub VaryQualityLevel()
' Get a bitmap.
Dim bmp1 As New Bitmap("c:\TestPhoto.jpg")

//Or you can use build-in method
//Dim jgpEncoder As ImageCodecInfo = GetEncoderInfo("image/jpeg");
Dim jgpEncoder As ImageCodecInfo = GetEncoder(ImageFormat.Jpeg)

' Create an Encoder object based on the GUID
' for the Quality parameter category.
Dim myEncoder As System.Drawing.Imaging.Encoder = System.Drawing.Imaging.Encoder.Quality

' Create an EncoderParameters object.
' An EncoderParameters object has an array of EncoderParameter
' objects. In this case, there is only one
' EncoderParameter object in the array.
Dim myEncoderParameters As New EncoderParameters(1)

Dim myEncoderParameter As New EncoderParameter(myEncoder, 50&)
myEncoderParameters.Param(0) = myEncoderParameter
bmp1.Save("c:\TestPhotoQualityFifty.jpg", jgpEncoder, myEncoderParameters)

myEncoderParameter = New EncoderParameter(myEncoder, 100&)
myEncoderParameters.Param(0) = myEncoderParameter
bmp1.Save("c:\TestPhotoQualityHundred.jpg", jgpEncoder, myEncoderParameters)

' Save the bitmap as a JPG file with zero quality level compression.
myEncoderParameter = New EncoderParameter(myEncoder, 0&)
myEncoderParameters.Param(0) = myEncoderParameter
bmp1.Save("c:\TestPhotoQualityZero.jpg", jgpEncoder, myEncoderParameters)

End Sub 'VaryQualityLevel



...


Private Function GetEncoder(ByVal format As ImageFormat) As ImageCodecInfo

Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageDecoders()

Dim codec As ImageCodecInfo
For Each codec In codecs
If codec.FormatID = format.Guid Then
Return codec
End If
Next codec
Return Nothing

End Function

Tuesday, August 18, 2009

Pass parameter to IN clause in SQL Server

Problem:

Suppose you have a query statement (either in Store procedure or Sql state) something like:

SELECT * FROM
myTable WHERE
Field IN(@DelimiterString)

and you want to execute this by passing a delimiter string '1, 2, 3, 4' to execute the query. Unfortunately, you can't do this. You will get error message "Conversion failed when converting the nvarchar value 'xxx,xxx' to data type int."

Solution:

There are several solutions to this problem something like split the value and save to temp table and read them back in IN clause. But i would like to introduce a simple solution by using dynamic sql. I may transform my query to:

exec('SELECT * FROM
myTable WHERE
Field IN(' + @DelimiterString + ')')


Finally, call your store procedure or sql statement accordingly with your delimiter parameter

Thursday, August 13, 2009

Pass Multiple Parameters to a Thread in C#

I think it would help someone working with Thread in C#. I found a good article at CodeProject:

Introduction

Have you wondered how you can send a parameter to a C# thread? Have you thought of using anonymous method calls and outer-variable semantics when you put a function in C# thread? If these questions interests you then you are at a right place to read the article further.

Background

I had a simple scinario of creating a C# thread then send a function that takes multiple input parameters and output a single value. I have been searching over net to find a help on that but could not find many. However, I have figured out a way to do that and thought of sharing the idea with other.

Using the code

Here is a sample code to create C# thread then send-in a delegate to the thread that casts a normal C# function and takes two input parameters. We also return an output from the same function when the thread execution is complete.

This sample has 3 simple C# projects.

PROJECT1: First project is a C# class library and has a one class inside. This class has a single function which takes two int input. The logic for this function is to multiply 'A' with 'N' times where 'A' = First input parameter and 'N' = second input parameter. Then it returns the calculated value to the caller. Following is a code snippet for that.

Collapse Copy Code
public class Thread1
{
public double Multiply(int lOpr1, int lOpr2)
{
double retVal = 1;
for (int i = 1; i <= lOpr2; i++)
{
retVal *= lOpr1;
}
return retVal;
}
}

PROJECT2: This project is a C# class library and also has a single class with a single function that takes two int inputs. The logic for this function is to add 'A' with 'N' times where 'A' and 'N' are input parameters to this function. This function also returns the calculated value to the caller. Following is a code snippet for that.

Collapse Copy Code
public class Thread2
{
public double Add(int lOpr1, int lOpr2)
{
double retVal = 0;
for (int i = 1; i <= lOpr2; i++)
{
retVal = retVal + lOpr1;
}
return retVal;
}
}

PROJECT3: This is a windows forms project with three text box and a button. On the button click event we will write a code to create two threads to call the above two class' that are to be executed within its own thread. (huh.. catching up with multithread). Following are the steps to do:

1. Declare two local variable and get the user input values in it.
2. Declare local variables to receive output value
3. Create an instance of a class from Project1
4. Create first thread thereby cast the above instance as a anonymous method to a type ‘delegate’. We assign the local variables created in step 1 as inputs to the anonymous method. This technique is called outter-variable semantics. We also assign a local variable to receive the return value - all in one step.
5. Start the first thread
6. Repeate step 3 to 5 to create second thread for the class from Project2
7. This step is to check whether both threads are done with the execution. If so write the output values to a text box.

Block of code for the button click event:

Collapse Copy Code
using System;
using System.Threading;
namespace MainThread
{
public partial class AppOne
{
private void btnMultiThread_Click(object sender, EventArgs e)
{
//1
int lOpr1 = Int32.Parse(txtInput1.Text);
int lOpr2 = Int32.Parse(txtInput2.Text);
//2
double getmul = 0;
double getadd = 0;
//3
Thread1 ClsMultiply = new Thread1();
//4
Thread MulThread = new Thread(delegate()
{
getmul = ClsMultiply.Multiply(lOpr1, lOpr2);
});
//5
MulThread.Start();
//6
Thread2 ClsAdd = new Thread2();
Thread AddThread = new Thread(delegate()
{
getadd = ClsAdd.Add(lOpr1, lOpr2);
});
AddThread.Start();
//7
while (MulThread.IsAlive || AddThread.IsAlive)
Thread.Sleep(1);

txtOutput.Text = "Addition of " + txtInput2.Text + " Times of " + txtInput1.Text + " = " + getadd
+ " ||| Multiplication of " + txtInput2.Text + " times of " + txtInput1.Text + " = " + getmul;
}
}
}

Remember to notice that, we can send any number of input parameters to a called method using this technique. Hope, you find this informative and simple to understand.