CF and display of Images

T

Tomppa

I simply want to display photos from a digital camera in my CF 2.0 app. Is
that to much to ask? After a day of Google searches it appears so.

Loading a Bitmap in CF simply sucks all the available memory until you get
an OOM exception.

I can load smaller jpg's but I need the same functionality that ImageViewer
provides. Take the CF card out of my camera and plug it into my CE device
and start viewing photos.

There are apps like this one written in C that appear to use another
approach for loading and displaying images.
http://www.bitbanksoftware.com/PQV.html

I tried to find a 3rd party control for purchase with no luck. Are there
any that anyone knows of?

Anyone have any suggestions. Anyone savvy in C want to write a control for
us CF developers?
 
C

C.C. \(aka Me\)

How large are your pictures? You shouldnt run out of memory just by loading
1 bitmap unless it is VERY large.

How are you loading the image - do you have some sample code that shows what
you are doing because it could jus be something silly that we could help
with!

I have loaded/displayed pictures in the past w/o any problems so I know it
can be done.
 
C

C.C. \(aka Me\)

One other thing to note in case you are using the System.Drawing.Image
class.

From MSDN:

Method:
public static Image FromFile(string filename)

Remarks:
"If the file does not have a valid image format or if GDI+ does not support
the pixel format of the file, this method throws an OutOfMemoryException
exception."


Maybe it has something to do with the file format you are loading?

Just a thought...
 
T

Tomppa

Here is a photo it fails on taken with a Nikon D70 resolution is 3008/2000
Size is 1.28MB
http://www.finnishtv.com/misc/DSC_2530.JPG

Smaller jpg's load fine.

Here is the code

GC.Collect();
Bitmap bmp = new Bitmap(FilePath);

or loading from a URL



HttpWebRequest Request = (HttpWebRequest)System.Net.WebRequest.Create(URL);

Request.AllowAutoRedirect = true;

Request.Accept = "*/*";

Request.AllowWriteStreamBuffering = true;

HttpWebResponse resp = (HttpWebResponse)Request.GetResponse();

System.IO.Stream stream = resp.GetResponseStream();
 
C

C.C. \(aka Me\)

Hmm..

First. pretty cool picture, I am tempted to set it as my desktop backgound
if you dont have any problems with me doing so!

Now...

If the picture was only an 8bit color then you would be looking at roughly
6MB (3008*2000). I am guessing that you are using a higher color display
on your PPC (maybe 16bit or something?) So double that to 12MB or more. I
could see how you may be getting a memory exception here if your device does
not have that much memory installed/available.

I wrote a very simple Windows app for my device and put a Picture box
control on it that would display the image you posted. I added a button that
when clicked would do the following:

System.Drawing.Bitmap bmp = new Bitmap(@"\Program
Files\ImageDisplay\sample.jpg");
pictureBox1.Image = bmp;

I built the application in Release mode and ran right from the device (no
debugging or VS stuff going on here).

It took maybe 15 seconds or so for the image to load and display. When I
looked at my memory usage I saw the following:

No app running: 8.77MB in use (from other programs on the device)
App started: 10.25MB in use
Image Loaded (picture box SizeMode set to StretchImage so it fits on the PDA
screen: 22MB in use
Image Loaded (picture box SizeMode set to Normal so it does not fit on the
PDA screen: 22MB in use

So it looks like it is taking around 10-12MB or so just to load and display
the image on the device. Keep in mind that this is a very simple program
(button and picure box control is it).

I have 64MB on my device so I am able to do it fine. How much memory does
your device have? Maybe try doing the same test as I did and see what your
memory usage is?

Not really any anwsers for you but at least some hope that it can work with
the picture you provided!
 
A

Alex Feinman [MVP]

To deal with this problem you need to use Imaging API. It supports creating
a scaled down bitmap without loading it entirely in memory. For CF2 it is
possible to wrap it using COM interop. Under CF 1 a C++ wrapper is needed.
 
T

Tomppa

Thanks for testing for me.

You are welcome to use the photo. Taken in Levi - Norther Finalnd - Lapland

Here is the device I am running on ICOP 128MB RAM 90MB Available
CE 5.0 BSP CF 2.0 http://www.finnishtv.com/misc/DSC_4131.JPG
This will eventually be mounted behind a 19in LCD panel and placed in a
picture frame.

Time to test on my PPC device I guess to isolate a potential problem with
the ICOP board config.

Running in Platform Builder connected to the device with VS 2005.

I've also tried packaging my app uith CEFileWiz and running directly on the
device and am getting the same OOM errors.

Here is my code that fails on load into the Bitmab object for larger size
bitmaps

private void DisplayImageFromFilePath(string FilePath)

{

try

{

if (FilePath != "")

{

//FilePath = @"\Hard Disk\DSC_4132.JPG";

Bitmap bmp;

try

{

bmp = new Bitmap(FilePath);

}

catch

{

picMain1.Image = null;

GC.Collect();

bmp = new Bitmap(FilePath);

}

Image img = s.FixedSize(bmp, Screen.PrimaryScreen.WorkingArea.Width,
Screen.PrimaryScreen.WorkingArea.Height);

//Image img = s.Crop(bmp, Screen.PrimaryScreen.WorkingArea.Width,
Screen.PrimaryScreen.WorkingArea.Height, AnchorPosition.Center);

picMain1.Top = 0;

picMain1.Left = 0;


picMain1.Image = img;


}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

}
 
T

Tomppa

Alex, Thanks for pointig this out. Can you provide a basic sample to get me
going in the right direction? I really have no idea where to start.
 
C

C.C. \(aka Me\)

One thought to help debug it is to maybe spread out some logging of the
value returned from GC.GetTotalMemory() so you can see how much memory is
actually used at each step of the process? At least you will know if it is a
true OOM error or something else?

On a side note what does that board run you in terms of price? It looks
pretty cool from the picture you gave! Might be able to find a use for it
myself...
 
A

Alex Feinman (MVP)

Tomppa said:
Alex, Thanks for pointig this out. Can you provide a basic sample to get me
going in the right direction? I really have no idea where to start.
I've put together a sample for you. It consists of a C++ DLL and a CF
form. This is a VS 2005 CF1 project. You can easily import it into
VS2003 (the managed part)

Please note that it won't run on the emulator as there are no image
encoders on it. A workaround is to use uncompressed data, but I did not
want to go that way.

http://www.alexfeinman.com/download.asp?doc=LoadBitmap.zip
 
T

Tomppa

Alex,

Thank you so much! This is exactly what I needed.

I assume that if I want to display an image from a URL I must 1st scrape the
bytes and store as a local file for display?

I now need to expand on your example to include EXIF data and rotate the
returned bitmap if the camera was at 90deg when the photo was taken.

Thanks! Thanks! Thanks!

Did I say Thanks

Tom
 
A

Alex Feinman [MVP]

The upcoming OpenNETCF SDF 2.0 will include a complete Imaging API wrapper,
including Rotation, Flip and brightness/contrast/gamma control.
I've experimented with wrapping NetworkStream from WebRequest to expose
IStream and feeding it to the IImagingFactory::CreateImageFromStream, but
that tries to seek in the stream to sniff the content and as a result blows
up as the networkstream does not support seeking. I'm hoping to get around
it though by picking the codec myself based on the content type header to
avoid sniffing
 
T

Tomppa

That's great is there an ETA on the OpenNETCF SDF 2.0?

I compiled your sample DLL for x86 and included it in my project CF2.0
project

It indeed displays the image at 1280/1024 but it is very distorted and
leaves about 100 pixels empty border around the image.

See example: http://finnishtv.com/misc/DSC_4134.JPG

After displaying about 6 of these images the app throws an out of memory
exception. I am calling FreeBitmapData()


I wrapped my call in a function as follows

public Bitmap GetBitmapUsingImagingAPI(string szFileName)

{

Rectangle ClientRectangle = new Rectangle(0, 0, 1280, 1024);

Bitmap bmp = null;

// Get bitmap size:

int intSize = GetBitmapDimensions(szFileName);

if (intSize == 0)

{

//Console.WriteLine("Failed to get bitmap size");

//MessageBox.Show("Failed to get bitmap size");

//return;

}

Size sz = new Size(intSize & 0xffff, intSize >> 16);

//Console.WriteLine(string.Format("Image size is {0} by {1}", sz.Width,
sz.Height));

int cx, cy;

cx = ClientRectangle.Width;

cy = cx * sz.Height / sz.Width;

if (cy > ClientRectangle.Height)

{

cy = ClientRectangle.Height;

cx = cy * sz.Width / sz.Height;

}

//pictureBox1.Width = cx;

//pictureBox1.Height = cy;

IntPtr pData;

int dataSize = LoadBitmapData(szFileName, cx, cy, out pData);

if (dataSize == 0)

{

//Console.WriteLine("Failed to load bitmap");

//return;

}

else

{

//Console.WriteLine("Loaded bitmap. Data size: " + dataSize);

}

bmp = new Bitmap(new StreamOnIntPtr(pData, dataSize));

FreeBitmapData(pData);

return bmp;

}
 
C

c.scholten

Alex - thank you for making this available.

I downloaded your example, and tried it with a bigger file (JPEG -
~2Mb), and it successfully gave me the message box with the dimensions
of the image, but wouldn't load the image into the Picture Box. I'm not
familiar with C++, and was unable to set up the included c++ project
for debugging. On the C# side, when the call was made to the DLL
function, it returned 0 bytes.

How is it possible to set the C++ project up for debugging? In the .NET
IDE (I'm using 2005), when I tried to access the project properties, it
indicated that there were no properties available to view.
 
C

Chris Tacke [MVP]

Bumping it with text might have been useful. From my viewer I have no
context on what this is about beyond the subject.

-Chris
 
A

Alex Feinman [MVP]

Sorry, I have not been watching this thread. I''ll try to look into this
over weekend. If you don't hear from me, send me an email
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top