Author |
Message |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Hi,
where's the best place to ask a question about trouble with System.Drawing.Imaging I couldn't find any special forum for this.
.NET Development30
|
|
|
|
 |
element109

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
What's the problem Include a sample.
|
|
|
|
 |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Okay, the problem is that I want to save a Bitmap as a JPEG file. I've found several how-tos on the net that describe how it works, with finding the right Encoder and setting parameters like for compression quality, but the Bitmap.Save() call throws an Invalid Argument exception. I have no idea what's wrong and there's no result when searching the web for this problem.
|
|
|
|
 |
nobugz

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
That exception is not documented for Image.Save(). Start by not tinkering with the encoder parameters. If that works, post the code that sets the encoder parameters and a call stack trace.
|
|
|
|
 |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
I don't know what you mean. I want to set encoding parameters and there is no similar solution with not setting those parameters. Does anyone have a working sample for saving a resampled JPEG image with a specified quality I don't get it. It looks highly complicated.
|
|
|
|
 |
nobugz

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
You didn't post your code, can't tell what's wrong with it. This worked well for me:
public static void SaveAsJPeg(Image img, int quality, string path) { if (quality < 0 || quality > 100) throw new ArgumentException("Quality out of range"); // Locate the JPEG encoder ImageCodecInfo jpeg = null; foreach (ImageCodecInfo encoder in ImageCodecInfo.GetImageEncoders()) if (encoder.FormatDescription == "JPEG") { jpeg = encoder; break; } // Setup to give the encoder the quality parameter EncoderParameters parms = new EncoderParameters(1); EncoderParameter qparam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); parms.Param[0] = qparam; // Now save the image img.Save(path, jpeg, parms); }
|
|
|
|
 |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Sorry for the long delay. I have now simplified my code and here it is: (Syntax highlighting function doesn't work here.)
using System; using System.Drawing; using System.Drawing.Imaging; using System.IO;
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { // Open image Image img_in = Image.FromFile(args[0]); // Write image ImageCodecInfo codec = null; foreach (ImageCodecInfo i in ImageCodecInfo.GetImageEncoders()) { if (i.MimeType == "image/jpeg") { codec = i; break; } } if (codec == null) throw new Exception("Jpeg codec not found");
EncoderParameters ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(Encoder.Quality, 80);
img_in.Save(Path.GetFileNameWithoutExtension(args[0]) + ".out.jpg", codec, ep); // This throws an ArgumentException with no further description of the problem } } }
|
|
|
|
 |
nobugz

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Too bad you didn't use my code, you would have been done a while ago. To get yours to work, change it like this:
ep.Param[0] = new EncoderParameter(Encoder.Quality, (Int64)80);
|
|
|
|
 |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
I can't see a difference in your code above. You didn't use Int64 (long) earlier, too. Also other code resources only use an Int32 (I assume, that is VB). But thanks for pointing this out, using long instead of int makes it work finally. I'm wondering why this pettiness isn't documented anywhere. I'd assume a value from 0 to 100 could be passed as int (which still seems to be the usual type for integer numbers) and doesn't require the double-sized long type.
|
|
|
|
 |
nobugz

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
The EncoderParameter class doesn't have a constructor that takes an Int32. It has got others that take Byte, Int16 and Int64. When you pass the quality as an "int", the compiler will use the constructor that takes Int64, the only one that can pass an "int" without truncating. When you pass the constant value "80", it will use the constructor that takes a Byte. GDI+ doesn't like that one.
Not very intuitive but GDI+ has lots of problems like that.
|
|
|
|
 |
LonelyPixel

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Now I see that Int32 isn't on the list. But today I temporarily had the code with an int variable instead of a literal number. That one didn't work, too. Strange.
|
|
|
|
 |
fookfulohan

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
I used a similar code in VB.NET but did mot specify INT64.
Howcome it work in VB.NET and not in C#
I find that C# is very unforgiving. Not very good for RAD.
|
|
|
|
 |
nobugz

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
VB.NET would do exactly the same. It is a subtle problem.
|
|
|
|
 |
fookfulohan

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
This code work in VB.NET w/o an explicitly casting it to INT64.
Dim imgCodec As ImageCodecInfo = GetEncoderInfo("image/jpeg")
Dim encParm As EncoderParameters = New EncoderParameters(1)
.
.
.
encParm.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 45)
Dim msImage As New MemoryStream()
pbImage.Image.Save(msImage, imgCodec, encParm) ' codec for image/jpeg, compression 45:1
I had the exact same code in C# (pbImage.Image.Save(msImage, imgCodec, encParm) and it won't work an exception occured.
Until I followed your suggestion and cast the encoder quality to int64.
|
|
|
|
 |
Jason Pryor

|
Posted: .NET Base Class Library, System.Drawing.Imaging trouble |
Top |
Speaking of quality issues, I'm trying to find out how to set the capture resolution (i.e. 300 dpi instead of 96 dpi). I've already posted the details of my question and the program background in this thread. Any help would be appreciated.
-Jason
|
|
|
|
 |
|