Search code examples
c#imagepngjpegirfanview

Why does IrfanView say my jpg file is a png file?


My utility is supposed to resize either .jpg or .png files.

It seems to work fine in one location (at work, where I don't have IrfanView installed). But at home, when I open a *.jpg and then save it (resized), I see:

enter image description here

However, the image still displays fine in either case (whether I select "Yes" or "No" in the dialog.

IOW, I'm able to load and save both jpgs and pngs, and they save as such, and display fine. But IrfanView claims they are messed up.

Actually, I'm not sure how the image is saved; I was assuming it just saved it in the proper format "behind the scenes" based on the extension. Anyway, as this is a rather simple utility, I will just show all the code:

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace FileResizingUtil
{
    public partial class FormFileResizer : Form
    {
        private Image _imgToResize;
        String _originalFilename = String.Empty;

        public FormFileResizer()
        {
            InitializeComponent();
        }

        private void buttonChooseImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                InitialDirectory = "c:\\",
                Filter = "JPG files (*.jpg)|*.jpg| PNG files (*.png)|*.png", FilterIndex = 2, RestoreDirectory = true
            };


            if (ofd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    _originalFilename = ofd.FileName;
                    _imgToResize = Image.FromFile(_originalFilename);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
            // If made it to here, it must be good
            String preamble = labelImgSelected.Text;
            labelImgSelected.Text = String.Format("{0}{1}", preamble, _originalFilename);
            textBoxOrigHeight.Text = _imgToResize.Height.ToString();
            textBoxOrigWidth.Text = _imgToResize.Width.ToString();
            buttonApplyPercentageChange.Enabled = true;
            //buttonResizeImage.Enabled = true;
        }

        private void buttonResizeImage_Click(object sender, EventArgs e)
        {
            // Really large images take awhile, so show an hourglass
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                var size = new Size { Height = Convert.ToInt32(textBoxNewHeight.Text), Width = int.Parse(textBoxNewWidth.Text) };
                // Two different ways of getting the int val
                Image resizedImg = FileResizeUtils.GetResizedImage(_imgToResize, size);

                String fileNameSansExtension = Path.GetFileNameWithoutExtension(_originalFilename);
                String fileNameExtension = Path.GetExtension(_originalFilename);
                String newFilename = String.Format("{0}{1}_{2}{3}", fileNameSansExtension, size.Height, size.Width, fileNameExtension);
                // If used a different extension (jpg where the original was png, or vice versa) would the Save be intelligent enough to actually save in the other format?
                resizedImg.Save(newFilename);

                MessageBox.Show(String.Format("Done! File saved as {0}", newFilename));
                Recycle();
            }
            finally
            {

                Cursor.Current = Cursors.Default;
            }
        }

        private void Recycle()
        {
            buttonResizeImage.Enabled = false;
            buttonApplyPercentageChange.Enabled = false;
            labelImgSelected.Text = "Image selected: ";
            textBoxOrigHeight.Text = String.Empty;
            textBoxOrigWidth.Text = String.Empty;
            // Retain the percentage vals, as it may be that all in a batch need to be the same pair of vals
        }

        private void buttonApplyPercentageChange_Click(object sender, EventArgs e)
        {
            int origHeight = _imgToResize.Height;
            int origWidth = _imgToResize.Width;

            // Two ways to convert the val
            double heightFactor = (double)numericUpDownHeight.Value / 100.0;
            double widthFactor = Convert.ToDouble(numericUpDownWidth.Value) / 100.0;
            if (heightFactor < 0 || widthFactor < 0)
            {
                // show an error - no negative values allowed- using updown, so that should not be possible
            }
            var newHeight = Convert.ToInt32(origHeight * heightFactor);
            var newWidth = Convert.ToInt32(origWidth * widthFactor);
            textBoxNewHeight.Text = newHeight.ToString();
            textBoxNewWidth.Text = newWidth.ToString();
            buttonResizeImage.Enabled = true;
        }

        private void textBoxNewHeight_TextChanged(object sender, EventArgs e)
        {
            EnableResizeButtonIfValidDimensionsEntered();
        }

        private void EnableResizeButtonIfValidDimensionsEntered()
        {
            if (String.IsNullOrWhiteSpace(textBoxOrigHeight.Text)) return;
            String candidateHeight = textBoxNewHeight.Text;
            String candidateWidth = textBoxNewWidth.Text;
            int validHeight;
            int validWidth;
            buttonResizeImage.Enabled = (int.TryParse(candidateHeight, out validHeight)) &&
                                        (int.TryParse(candidateWidth, out validWidth));
        }

        private void numericUpDownHeight_ValueChanged(object sender, EventArgs e)
        {
            if (checkBoxRetainRatio.Checked)
            {
                numericUpDownWidth.Value = numericUpDownHeight.Value;
            }
        }

        private void numericUpDownWidth_ValueChanged(object sender, EventArgs e)
        {
            if (checkBoxRetainRatio.Checked)
            {
                numericUpDownHeight.Value = numericUpDownWidth.Value;
            }
        }

    }
}

..and the GUI (just prior to hitting the "Resize Image" button:

enter image description here

UPDATE

Based on Eugene Sh.'ls comment, I changed my Save method to the following block:

bool success = true;
. . .
if (fileNameExtension != null && fileNameExtension.ToLower().Contains("jpg"))
{
    resizedImg.Save(newFilename, ImageFormat.Jpeg);
}
else if (fileNameExtension != null && 
         fileNameExtension.ToLower().Contains("png"))
{
    resizedImg.Save(newFilename, ImageFormat.Png);
}
else
{
    success = false;
}

if (success)
{
    MessageBox.Show(String.Format("Done! File saved as {0}", newFilename));
}
else
{
    MessageBox.Show("Something went awry. The file was not saved");
}

UPDATE 2

So here is my new code, implementing the suggestion, and supporting several new file types:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace FileResizingUtil
{
    public partial class FormFileResizer : Form
    {
        private Image _imgToResize;
        String _originalFilename = String.Empty;

        public FormFileResizer()
        {
            InitializeComponent();
        }

        private void buttonChooseImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                InitialDirectory = "c:\\",
                Filter = "JPG files (*.jpg)|*.jpg| PNG files (*.png)|*.png| BMP files (*.bmp)|*.bmp| TIFF files (*.tiff)|*.png| ICO files (*.ico)|*.ico| EMF files (*.emf)|*.emf| WMF files (*.wmf)|*.wmf",
                    FilterIndex = 1, RestoreDirectory = true
            };


            if (ofd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    _originalFilename = ofd.FileName;
                    _imgToResize = Image.FromFile(_originalFilename);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
            if (String.IsNullOrWhiteSpace(_originalFilename)) return;
            // If made it to here, it must be good
            String preamble = labelImgSelected.Text;
            labelImgSelected.Text = String.Format("{0}{1}", preamble, _originalFilename);
            textBoxOrigHeight.Text = _imgToResize.Height.ToString();
            textBoxOrigWidth.Text = _imgToResize.Width.ToString();
            buttonApplyPercentageChange.Enabled = true;
        }

        private void buttonResizeImage_Click(object sender, EventArgs e)
        {
            bool success = true;
            // Really large images take awhile, so show an hourglass
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                // Two different ways of getting the int val
                var size = new Size { Height = Convert.ToInt32(textBoxNewHeight.Text), Width = int.Parse(textBoxNewWidth.Text) };
                Image resizedImg = FileResizeUtils.GetResizedImage(_imgToResize, size);

                String fileNameSansExtension = Path.GetFileNameWithoutExtension(_originalFilename);
                String fileNameExtension = Path.GetExtension(_originalFilename);
                String newFilename = String.Format("{0}{1}_{2}{3}", fileNameSansExtension, size.Height, size.Width, fileNameExtension);
                if (fileNameExtension != null && fileNameExtension.ToLower().Contains("jpg"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Jpeg);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("png"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Png);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("bmp"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Bmp);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("ico"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Icon);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("tiff"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Tiff);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("emf"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Emf);
                }
                else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("wmf"))
                {
                    resizedImg.Save(newFilename, ImageFormat.Wmf);
                }
                else
                {
                    success = false;
                }

                MessageBox.Show(success
                    ? String.Format("Done! File saved as {0}", newFilename)
                    : "Something went awry. The file was not saved");
                Recycle();
            }
            finally
            {

                Cursor.Current = Cursors.Default;
            }
        }

        private void Recycle()
        {
            buttonResizeImage.Enabled = false;
            buttonApplyPercentageChange.Enabled = false;
            labelImgSelected.Text = "Image selected: ";
            textBoxOrigHeight.Text = String.Empty;
            textBoxOrigWidth.Text = String.Empty;
            // Retain the percentage vals, as it may be that all in a batch need to be the same pair of vals
        }

        private void buttonApplyPercentageChange_Click(object sender, EventArgs e)
        {
            int origHeight = _imgToResize.Height;
            int origWidth = _imgToResize.Width;

            // Two ways to convert the val
            double heightFactor = (double)numericUpDownHeight.Value / 100.0;
            double widthFactor = Convert.ToDouble(numericUpDownWidth.Value) / 100.0;
            if (heightFactor < 0 || widthFactor < 0)
            {
                // show an error - no negative values allowed- using updown, so that should not be possible
            }
            var newHeight = Convert.ToInt32(origHeight * heightFactor);
            var newWidth = Convert.ToInt32(origWidth * widthFactor);
            textBoxNewHeight.Text = newHeight.ToString();
            textBoxNewWidth.Text = newWidth.ToString();
            buttonResizeImage.Enabled = true;
        }

        private void textBoxNewHeight_TextChanged(object sender, EventArgs e)
        {
            EnableResizeButtonIfValidDimensionsEntered();
        }

        private void EnableResizeButtonIfValidDimensionsEntered()
        {
            if (String.IsNullOrWhiteSpace(textBoxOrigHeight.Text)) return;
            String candidateHeight = textBoxNewHeight.Text;
            String candidateWidth = textBoxNewWidth.Text;
            int validHeight;
            int validWidth;
            buttonResizeImage.Enabled = (int.TryParse(candidateHeight, out validHeight)) &&
                                        (int.TryParse(candidateWidth, out validWidth));
        }

        private void numericUpDownHeight_ValueChanged(object sender, EventArgs e)
        {
            if (checkBoxRetainRatio.Checked)
            {
                numericUpDownWidth.Value = numericUpDownHeight.Value;
            }
        }

        private void numericUpDownWidth_ValueChanged(object sender, EventArgs e)
        {
            if (checkBoxRetainRatio.Checked)
            {
                numericUpDownHeight.Value = numericUpDownWidth.Value;
            }
        }

    }
}

Solution

  • From the Image.Save documentation:

    If no encoder exists for the file format of the image, the Portable Network Graphics (PNG) encoder is used. When you use the Save method to save a graphic image as a Windows Metafile Format (WMF) or Enhanced Metafile Format (EMF) file, the resulting file is saved as a Portable Network Graphics (PNG) file. This behavior occurs because the GDI+ component of the .NET Framework does not have an encoder that you can use to save files as .wmf or .emf files.

    If you want to save in a different format, use the overloaded Save method, taking format as a second parameter:

    Save(String, ImageFormat)