?
Solved

foreach problems

Posted on 2011-04-29
15
Medium Priority
?
552 Views
Last Modified: 2012-05-11
I'm using a foreach loop to run through a folder of images.  I have the code set to display the images so that I know something is happening, but only one of the images seems to be displaying. Here is the code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace NewImageReader
{
   
       
    public partial class JpegReader : Form
    {

        private void LUBits()
        {

            foreach (string img in Directory.GetFiles(@"C:\Users\Giles Kingsley\Desktop\ProjectImages"))
            {
                Bitmap bmp = new Bitmap(img) as Bitmap;

                //Display the image
                imageHolder.Image = bmp;
                System.Threading.Thread.Sleep(1);

                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                System.Drawing.Imaging.BitmapData bmpData =
                    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bmp.PixelFormat);

                // Get the address of the first line.
                IntPtr ptr = bmpData.Scan0;
                // Declare an array to hold the bytes of the bitmap.
                int bytes = bmpData.Stride * bmp.Height;
                byte[] rgbValues = new byte[bytes];

                // Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

                // unlock the bitmap buffer
                bmp.UnlockBits(bmpData);

            }
        }
        private void button1_Click_1(object sender, EventArgs e)
        {
            LUBits();
        }
        public JpegReader()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            LUBits();
        }
    }
}
0
Comment
Question by:antarctican69
  • 5
  • 3
  • 3
  • +3
15 Comments
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 35495176
Wrap the code inside the loop with a try / catch to ensure an exception isn't kicking it out.
0
 
LVL 7

Expert Comment

by:OklahomaDave
ID: 35495181
May be a silly question, but is there any chance there's a non-image file in that folder, and the app is just crashing when it tries to process it as an image??
0
 

Author Comment

by:antarctican69
ID: 35495357
there is nothing but images in the folder.  Tried the try/catch wrapper, but no dice.  The program is not going through all the files, that is the problem.  Could it be where I have the display code?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 13

Expert Comment

by:iHadi
ID: 35495843
To debug the problem try the following:

1. Can you modify your code or set a breakpoint to make sure that all the images pathes are returned from the Getfiles() method.

2. If all the files are in the string array, make sure that the images are not drawn over each other. Check if the image that is drawn is the last one in the array.

3. Try using GDI+ methods to draw the images and make sure that all files are in correct format.
0
 
LVL 11

Expert Comment

by:saragani
ID: 35496612
imageHolder.Image = bmp;
I can assume that imageHolder is a picturebox or something like that.
Since you are itterating and setting the same property for each image, only the last image will be shows on your picturebox.
0
 
LVL 7

Expert Comment

by:OklahomaDave
ID: 35496967
Problems with timed GUI updates always make me suspect painting and refresh issues. I suspect that since all the updating is happening in a single event, with a one-second delay as each image is loaded into the control, the form never has a chance to repaint itself with each update, so you only see one of the updates as the form has only refreshed itself one time.

There are a few ways to handle this.  At a minimum, I would call the Refresh method of the control hosting the image (presumably a PictureBox?) after the new image is loaded.bIf a pure call to Refresh doesn't solve the problem, I'd consider spinning up a background thread to fire every second and marshal a call back to the GDI thread to perform the update.  I'll see if I can spin up an example for you in a sec...

-David


0
 
LVL 11

Expert Comment

by:saragani
ID: 35496973
The sleep is 1ms not 1 second.
0
 
LVL 7

Accepted Solution

by:
OklahomaDave earned 2000 total points
ID: 35497211
Okay, my friend, I won't promise this is the best, most elegant way to accomplish your objective, but it works, and perhaps you can tailor it to your needs. It fires up a background thread and a GUI update delegate to refresh the image control after each new image is sent.

I hope this helps.

=David

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;


    public partial class JpegReader : Form
    {
        delegate void ImageUpdaterDelegate(PictureBox imageHost, Bitmap image);

        Thread updaterThread;

        public static void ImageUpdater(PictureBox imageHost, Bitmap image)
        {
            if (imageHost.InvokeRequired)
            {
                imageHost.Invoke(new ImageUpdaterDelegate(ImageUpdater), new object[]{imageHost, image});
            }
            else
            {
                imageHost.Image = image;
                imageHost.Refresh();
            }
        }


        private void LUBits(String img)
        {


                Console.WriteLine(img);
                Bitmap bmp = new Bitmap(img) as Bitmap;

                ImageUpdater(imageHolder, bmp);

                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                System.Drawing.Imaging.BitmapData bmpData =
                    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bmp.PixelFormat);

                // Get the address of the first line.
                IntPtr ptr = bmpData.Scan0;
                // Declare an array to hold the bytes of the bitmap.
                int bytes = bmpData.Stride * bmp.Height;
                byte[] rgbValues = new byte[bytes];

                // Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

                // unlock the bitmap buffer
                bmp.UnlockBits(bmpData);

        }
        public void StartUpdate()
        {
            foreach (string img in Directory.GetFiles(@"your path goes here"))
            {
                LUBits(img);
                Thread.Sleep(1000);
            }
            
        }
        private void button1_Click_1(object sender, EventArgs e)
        {
            updaterThread = new Thread(new ThreadStart(this.StartUpdate));
            updaterThread.Start();
        }
        public JpegReader()
        {
            InitializeComponent();
        }

    }

Open in new window

0
 

Author Comment

by:antarctican69
ID: 35497280
Hey thanks for all the ideas, I will have to get back to you on how they worked, as other matters press, but I think that root of the display problem is in the problems you've mentioned.  More work to follow, but thanks again
0
 
LVL 7

Expert Comment

by:OklahomaDave
ID: 35497300
Antarctican69,

You're welcome. Please remember to let those of us who offered help know how this worked out if you're not closing the issue right now...
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 35497867
You're trying to perform long-running logic in the same thread that all of your GUI controls are created on. As OklahomaDave demonstrates, you should spawn a separate thread to perform the long-running logic.

When you you do lengthy logic in a GUI object's event handler, provided it an object created on the main thread, you cause the message pump that processes messages like, "move window", "draw button", etc. to freeze up and not process any messages until the long-running logic completes. You have probably run into "Form not responding..." messages in your title bar from time to time. This is why.

The quick-and-dirty way to handle this is to use Application.DoEvents(). But this is generally seen as an improper way to handle this scenario. As already mentioned, a separate thread overcomes this problem.

In addition to using a custom Thread object, you may consider looking into the ThreadPool or the BackgroundWorker. Both have internal threads to handle lengthy processes, but each handles creation and destruction of threads internally---you just worry about your logic and updating your UI appropriately.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 35497871
provided it an object created on the main thread
Aahhh typos...   That should read:

    provided it is not an object created on the main thread
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 35497875
P.S.

Calling Refresh(), Update(), or Invalidate() won't work because of the aforementioned message blocking.
0
 

Author Closing Comment

by:antarctican69
ID: 35498716
You are da' man.  I have no idea what you did, but the code works for what I want.  I'm really new at this, so it's nice to have some ready-bake code to work off.
0
 
LVL 7

Expert Comment

by:OklahomaDave
ID: 35499136
You're welcome, antarctican! I'm glad it worked out for you!

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question