Search code examples
c#.netimagewinformspicturebox

Rotate Image and View Next Page


I’m using WinForms for my application. I’m building an image viewer. My application opens image documents (.tif) files. The application has the ability to go to the next page.

The issue is, that every time I try to rotate the image and click next, the image stays on the same page but the page number increments.

Why can’t I see the images when it’s on rotate?

How can I rotate the image and go to the next page?

In the link below I've provided a test tif document for testing purposes: http://www.filedropper.com/sampletifdocument5pages

My Code:

    FileStream _stream;
    Image _myImg; // setting the selected tiff
    string _fileName;
    private int intCurrPage = 0; // defining the current page
    private int intTotalPages = 0;


    private void Open_Btn_Click(object sender, EventArgs e)
    {
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            lblFile.Text = openFileDialog1.FileName;

            // Before loading you should check the file type is an image

            if (_myImg == null)
            {
                _fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
                File.Copy(@lblFile.Text, _fileName);
                _stream = new FileStream(_fileName, FileMode.Open, FileAccess.Read);
                pictureBox1.Image = Image.FromStream(_stream);
            }

            //pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
            pictureBox1.Size = new Size(750, 1100);

            // Reset the current page when loading a new image.
            intCurrPage = 1;
            intTotalPages = pictureBox1.Image.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);

            lblNumPages.Text = intTotalPages.ToString();
            lblCurrPage.Text = "1";


        }
     }

    private void NextPage_btn_Click(object sender, EventArgs e)
    {
        if (intCurrPage <= (intTotalPages - 1))
        {
            if(Radio_90_Rotate.Checked)
            {
                pictureBox1.Image.RotateFlip(RotateFlipType.Rotate90FlipNone);
            }
            if(Radio_180_Rotate.Checked)
            {
                pictureBox1.Image.RotateFlip(RotateFlipType.Rotate180FlipNone);
            }

            // Directly increment the active frame within the image already in the PictureBox
            pictureBox1.Image.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, intCurrPage);

            //page increment (Go to next page)
            intCurrPage++;


            // Refresh the PictureBox so that it will show the currently active frame
            pictureBox1.Refresh();

            lblCurrPage.Text = intCurrPage.ToString();

        }
    }

enter image description here


Solution

  • The RotateFlip function will change the source image and flatten it to only one page. This means we need to make copies each time you view a new page that has rotation applied.

    In this solution, I use the source image and simply change pages when no rotation is applied. But when rotation is set, then a Image copy is made for each page and then the rotation is applied to the copy only.

    Using your sample image it takes time to load each page. So I implemented a simple label message to let the user know it's working.

    Also, you may consider looking into classes prebuilt for tiff files like: https://bitmiracle.github.io/libtiff.net/

    private Image _Source = null;
    private int _TotalPages = 0;
    private int _CurrentPage = 0;
    
    private void Frm_TiffViewer_Load(object sender, EventArgs e)
    {
        lbl_WaitMessage.Visible = false;
    
        // These two options can be adjusted as needed and probably should be set in the form control properties directly:
        pictureBox1.Size = new Size(750, 1100);
        pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
    }
    
    private void ShowProcessingImageLabel()
    {
        lbl_WaitMessage.Visible = true;
        Application.DoEvents();
    }
    
    private void DisplayPage(int PageNumber, RotateFlipType Change)
    {
        if (pictureBox1.Image != null && pictureBox1.Image != _Source)
        {
            // Release memory for old rotated image
            pictureBox1.Image.Dispose();
        }
    
        //  set the variable to null for easy GC cleanup
        pictureBox1.Image = null;
    
        _Source.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, PageNumber - 1);
    
        pictureBox1.Image = new Bitmap(_Source);
    
        pictureBox1.Image.RotateFlip(Change);
    
        pictureBox1.Refresh();
    }
    
    private void DisplayPage(int PageNumber)
    {
        ShowProcessingImageLabel();
    
        this.lblCurrPage.Text = PageNumber.ToString();
    
        // You could adjust the PictureBox size here for each frame  OR adjust the image to fit the picturebox nicely.
        if (Radio_90_Rotate.Checked == true)
        {
            DisplayPage(PageNumber, RotateFlipType.Rotate90FlipNone);
            lbl_WaitMessage.Visible = false;
            return;
        }
        else if (Radio_180_Rotate.Checked == true)
        {
            DisplayPage(PageNumber, RotateFlipType.Rotate180FlipNone);
            lbl_WaitMessage.Visible = false;
            return;
        }
    
        if (pictureBox1.Image != _Source)
        {
            if (pictureBox1.Image != null)
            {
                // Release memory for old copy and set the variable to null for easy GC cleanup
                pictureBox1.Image.Dispose();
                pictureBox1.Image = null;
            }
    
            pictureBox1.Image = _Source;
        }
    
        pictureBox1.Image.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, PageNumber-1);
    
        pictureBox1.Refresh();
    
        lbl_WaitMessage.Visible = false;
    }
    
    
    private void Open_Btn_Click(object sender, EventArgs e)
    {
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            // Before loading you should check the file type is an image
    
            this._Source = Image.FromFile(openFileDialog1.FileName);
    
            _TotalPages = _Source.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
            _CurrentPage = 1;
    
            lblCurrPage.Text = "1";
            lblFile.Text = openFileDialog1.FileName;
            this.lblNumPages.Text = _TotalPages.ToString();
    
            DisplayPage(_CurrentPage);
        }
    }
    
    private void NextPage_btn_Click(object sender, EventArgs e)
    {
        if (_CurrentPage < _TotalPages)
        {
            _CurrentPage++;
        }
    
        DisplayPage(_CurrentPage);
    }
    
    private void b_Previous_Click(object sender, EventArgs e)
    {
        if (_CurrentPage > 1)
        {
            _CurrentPage--;
        }
    
        DisplayPage(_CurrentPage);
    }
    
    private void Radio_90_Rotate_CheckedChanged(object sender, EventArgs e)
    {
        DisplayPage(_CurrentPage);
    }
    
    private void Radio_180_Rotate_CheckedChanged(object sender, EventArgs e)
    {
        DisplayPage(_CurrentPage);
    }
    
    private void Radio_0_Default_CheckedChanged(object sender, EventArgs e)
    {
        DisplayPage(_CurrentPage);
    }