I'm using a remote url for a PImage. It's a jpg from a cam. I'm grabbing it and sending it to a image() every sec. Switching to a new cam every 10 secs. Every hour or so, the script crashes due to a 502 error, since the image was not successfully downloaded.
I'm attempting to setup a script that looks at the image using requestImage(), does a quick error check, and skips draw of that image if it returns a 0 or -1. Which should be simple enough. But...
How can you send a constantly updating url to requestImage() if its parameters refuse to accept anything other than a static single filename in a string and it lives in setup() / pre-process?
Anyone run into this issue before? Or am I missing something?
Here is the code. Note: cams are not active at the moment, so there are placeholders in the array...;
Thanks for looking!
PImage webImg;
PImage testImg;
int timer;
String[] camlist = {
"random_url_with_JPG_here",
"random_url_with_JPG_here",
"random_url_with_JPG_here"
};
//find length of array
int camListLength = int(random(camlist.length));
void setup() {
testImg = requestImage(webImg, "jpg");
noCursor();
fullScreen();
background(0);
}
void draw() {
if (millis() - timer >= 10000) {
camLoad();
timer = millis();
} else {
displayWebImage();
}
}
void camLoad() {
//find length of array
camListLength = int(random(camlist.length));
}
void displayWebImage() {
// load random cam url into 'webImg'
webImg = loadImage(camlist[camListLength], "jpg");
// test load
println(testImg.width);
if (testImg.width == 0) {
println("Not Loaded");
} else if (testImg.width == -1) {
println("random error");
} else {
// display 'webImage'
image(webImg, 0, 0, 800, 480);
// cache cleanup
g.removeCache(webImg);
delay(1000);
// frame count
println(frameCount+" "+g.getCache(webImg));
}
}
It's true that for 95% of people, it's a very bad idea to create images in the draw() function. Most programs should load all of the images at the beginning, in the setup() function.
But if you're loading images that you don't know ahead of time, then nothing is stopping you from creating images in the draw() function. You can absolutely call requestImage() from inside the draw() function.
But note that the requestImage() function runs in the background, so your code keeps executing while the image is requested. From the reference:
This function loads images on a separate thread so that your sketch doesn't freeze while images load during setup(). While the image is loading, its width and height will be 0. If an error occurs while loading the image, its width and height will be set to -1.
This means that the image won't be loaded until a couple second later, so you can't use your image variable right away. You're fixing this using a call to delay(), but you're probably better off just using the loadImage() function instead. From the reference:
If the file is not available or an error occurs, null will be returned and an error message will be printed to the console. The error message does not halt the program, however the null value may cause a NullPointerException if your code does not check whether the value returned is null.
...
Depending on the type of error, a PImage object may still be returned, but the width and height of the image will be set to -1. This happens if bad image data is returned or cannot be decoded properly. Sometimes this happens with image URLs that produce a 403 error or that redirect to a password prompt, because loadImage() will attempt to interpret the HTML as image data.
That function does not run in the background, so the code only continues after the image is fully loaded.
Related
I am trying to fetch Customer data to parse them into customer object to display on TableView. The following code sometimes works, sometimes not. Whenever it does crash, it shows Customer data is empty in the foreach loop even though I run the same code every time. I do not have clue what could be wrong in this circumstances. I am quite new on this platform. If I am missing anything/ extra information, please let me know.
namespace TableViewExample
{
public partial class MyDataServices : ContentPage
{
private ODataClient mODataClient;
private IEnumerable <IDictionary<string,object>> Customers;
public MyDataServices ()
{
InitializeComponent ();
InitializeDataService ();
GetDataFromOdataService ();
TableView tableView = new TableView{ };
var section = new TableSection ("Customer");
foreach (var customers in Customers) {
//System.Diagnostics.Debug.WriteLine ((string)customers ["ContactName"]);
var name = (string)customers ["ContactName"];
var cell = new TextCell{ Text = name };
section.Add (cell);
}
tableView.Root.Add (section);
Padding = new Thickness (10, 20, 10, 10);
Content = new StackLayout () {
Children = { tableView }
};
}
private void InitializeDataService(){
try {
mODataClient = new ODataClient ("myURL is here");
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
private void GetDataFromOdataService (){
try {
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
}
}
Its hard helping out here, however here are some things to consider:-
It sounds like the dataservice could either be not contactable / offline; too busy or it could even be throwing an exception itself and returning a data response that you are not expecting to receive, that then triggers an exception and crash in your application as your always expecting an exact response without catering for any abnormal responses / events.
If you are contacting an external service over the internet it may just be your internet connection is slow / faulty and not returning the information fast enough as other possibilities.
In your code you are assuming that you always get a response from the server - and that this response will always be of an anticipated structure that your expecting to decode - without factoring in any possibility of abnormal responses returned by the dataservice. I have not used ODataClient personally, so not sure how it behaves in the event of maybe no data received / timeout or in your case the dataservice and how it behaves internally in the response to a bad-request etc.
I am assuming an exception would get thrown, and you do get your debug line executed indicating a failure.
You may want to also adjust this statement so that you write out the exception as well, i.e.:-
private void GetDataFromOdataService ()
{
try
{
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ERROR!" + ex.ToString());
}
}
If there was a bad response, then the line at Customers = ..... would throw the exception as there may be no Customers returned or some other information packaged in the response from the dataservice.
The Customers variable would also be null at this point I am assuming due to this failing.
So when you get back to your code at foreach (var customers in Customers) { it will then throw a null reference exception as Customers is infact null.
As all your current code executes in the constructor without any try and catch block around this, it will also crash your application at this point as well.
Also you are doing all of this work in the constructor. Try seperating this out. I haven't investigated exactly where the constructor gets called in an iOS page life-cycle, however, if it is in the viewDidLoad, then you have something like 10 seconds for everything to complete, otherwise it will exit automatically. I imagine in your case, this isn't applicable however.
Going forward also try putting your layout controls in the constructor, and move your data task to maybe the OnAppearing override instead.
Using async would definitely be advisable as well, but remember you need to inspect the response from your dataservice, as the error could be embedded within the response also and you will need to detect when it is OK to process the data.
I try to implement kind of a Videostream that relays on simple JPEG Files.
On my server, a JPEG is being created cyclically by an external Camera.
And I just want to include this Picture in my GWT Application.
My first idea to reload the Picture by a Timer was very simple but not so good: The client opens a connection for each reload-cycle, and the Picture flickers (at least in Firefox).
How could I solve these problems? I was thinking about something like "Web-Sockets", but I don't really know how to do.
I want to avoid a single connection for each reload. My idea was to have something like an open connection that just provides a new Picture as often as the Client asks for.
And how could I avoid the flickering when swapping the Picture?
Any ideas are welcome!
Regards, VanDahlen
A solution to avoid flickering is to have two images absolutely positioned in the same location. A timer would load one or other alternatively in each frame. Set a load handler to each image, so that it changes the z-index when the image is loaded and it restarts the timer.
Adding an extra parameter to the image url, makes the browser ask the server each time to bypass its cache.
If the time between frames is small, normally the browser will re-use the same connection if keep-alive is correctly configured in your server. It normally is enabled with a typical value of 5-15 seconds which you could increase, so if your .jpg images are updated with this periodicity, you don't have to worry and look for a better solution.
I propose a UI solution based on these ideas. But it will work as well if you use a websocket/comet mechanism giving you the last .jpg file in base64 format (just change the url by the value returned).
GWT code:
public void onModuleLoad() {
final Image i1 = new Image();
i1.setWidth("400px");
final Image i2 = new Image();
i2.setWidth("400px");
AbsolutePanel panel = new AbsolutePanel();
panel.add(i1, 0, 0);
panel.add(i2, 0, 0);
panel.setSize("600px", "400px");
RootPanel.get().add(panel);
// You could change this by base64 data if you use comet/websockets
String url = "my_image_url.jpg?";
final Timer loadNext = new Timer() {
boolean b;
int c;
public void run() {
// the counter parameter forces to load the next frame instead of using cache
if (b = !b) {
i1.setUrl(url + c++);
} else {
i2.setUrl(url + c++);
}
}
};
i1.addLoadHandler(new LoadHandler() {
public void onLoad(LoadEvent event) {
i1.getElement().getStyle().setZIndex(1);
i2.getElement().getStyle().setZIndex(0);
loadNext.schedule(1000);
}
});
i2.addLoadHandler(new LoadHandler() {
public void onLoad(LoadEvent event) {
i1.getElement().getStyle().setZIndex(0);
i2.getElement().getStyle().setZIndex(1);
loadNext.schedule(1000);
}
});
loadNext.schedule(1000);
}
If you want to use gwtquery, the code is obviously smaller:
// You could change this by base64 data if you use comet/websockets
final String url = "my_image_url.jpg?";
final GQuery images = $("<img/><img/>").appendTo(document);
images.css($$("position: fixed, top: 10px, left: 600px, width: 400px"));
final Timer timer = new Timer() {
int c;
public void run() {
images.eq(c%2).attr("src", url + c++);
}
};
images.bind("load", new Function(){
public void f() {
$(this).css($$("z-index: 1")).siblings("img").css($$("z-index: 0"));
timer.schedule(1000);
}
});
timer.schedule(1000);
I'm developing for Windows Phone XNA and would like to load textures with a smaller size to decrease memory impact where the full image isn't required.
My current solution is to use a rendertarget to draw and return that rendertarget as a smaller texture to use:
public static Texture2D LoadResized(string texturePath, float scale)
{
Texture2D texLoaded = Content.Load<Texture2D>(texturePath);
Vector2 resizedSize = new Vector2(texLoaded.Width * scale, texLoaded.Height * scale);
Texture2D resized = ResizeTexture(texLoaded, resizedSize);
//texLoaded.Dispose();
return resized;
}
public static Texture2D ResizeTexture(Texture2D toResize, Vector2 targetSize)
{
RenderTarget2D renderTarget = new RenderTarget2D(
GraphicsDevice, (int)targetSize.X, (int)targetSize.Y);
Rectangle destinationRectangle = new Rectangle(
0, 0, (int)targetSize.X, (int)targetSize.Y);
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.Transparent);
SpriteBatch.Begin();
SpriteBatch.Draw(toResize, destinationRectangle, Color.White);
SpriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
return renderTarget;
}
This works in that the texture gets resized but from memory usage it looks like the Texture "texLoaded" doesn't get freed. When using the uncommented Dispose method the SpriteBatch.End() will throw a disposed exception.
Any other way to load the texture resized for less memory usage?
Your code is almost ok. There's a minor bug in it.
You'll probably notice that it only throws that exception the second time that you call LoadResized for any given texture. This is because ContentManager keeps an internal cache of content that it loads - it "owns" everything that it loads. That way, if you load something twice, it just gives you back the cached object. By calling Dispose you are disposing the object in its cache!
The solution, then, is to not use ContentManager to load your content - at least not the default implementation. You can inherit your own class from ContentManager that does not cache items, like so (code is based on this blog post):
class FreshLoadContentManager : ContentManager
{
public FreshLoadContentManager(IServiceProvider s) : base(s) { }
public override T Load<T>(string assetName)
{
return ReadAsset<T>(assetName, (d) => { });
}
}
Pass in Game.Services to create one. Don't forget to set the RootDirectory property.
Then use this derived content manager to load your content. You now can safely (and now should!) Dispose of all content that you load from it yourself.
You may also wish to attach an event handler to the RenderTarget2D.ContentLost event, so that, in the event the graphics device is "lost", the resized texture gets recreated.
I'm setting out to create a weather model display tool (web application), and from what I've seen, I'm really liking the idea of using Google Web Tools, and especially the SmartGWT toolkit. My one biggest sticking point at this point is finding some way to create a sort of image "looper" (displaying all images in a particular "set" one after another, not unlike a slide show). For reference, I need functionality (at least on a basic level) similar to this: http://rapidrefresh.noaa.gov/hrrrconus/jsloop.cgi?dsKeys=hrrr:&runTime=2012053007&plotName=cref_sfc&fcstInc=60&numFcsts=16&model=hrrr&ptitle=HRRR%20Model%20Fields%20-%20Experimental&maxFcstLen=15&fcstStrLen=-1&resizePlot=1&domain=full&wjet=1 (though it certainly need not be exactly like that).
Does anyone know of (ideally) some sort of GWT module that can do image looping? Or if not, does it sound like something an intermediate programmer could figure out without too much trouble (I'm willing to accept a challenge), even if I've never explicitly used GWT before? I'm sure I could whip together something that pulls each image in as it goes through a loop, but prefetching them would be even more ideal.
Please comment if you need clarification on anything!
As far as I'm aware there's not a pre-fab solution to do this, although maybe SmartGWT has something I don't know about. In any case, it won't be too hard to roll your own. Here's some code to get you started:
public class ImageLooper extends Composite {
// List of images that we will loop through
private final String[] imageUrls;
// Index of the image currently being displayed
private int currentImage = 0;
// The image element that will be displayed to the user
private final Image image = new Image();
// The Timer provides a means to execute arbitrary
// code after a delay or at regular intervals
private final Timer imageUpdateTimer = new Timer() {
public void run() {
currentImage = (currentImage + 1) % images.length;
image.setUrl(imageUrls[currentImage]);
}
}
// Constructor. I'll leave it to you how you're going to
// build your list of image urls.
public ImageLooper(String[] imageUrls) {
this.imageUrls = imageUrls;
// Prefetching the list of images.
for (String url : imageUrls)
Image.prefetch(url);
// Start by displaying the first image.
image.setUrl(imageUrls[0]);
// Initialize this Composite on the image. That means
// you can attach this ImageLooper to the page like you
// would any other Widget and it will show up as the
// image.
initWidget(image);
}
// Call this method to start the animation
public void playAnimation() {
// Update the image every two seconds
imageUpdateTimer.scheduleRepeating(2000);
}
// Call this method to stop the animation
public void stopAnimation() {
imageUpdateTimer.cancel();
}
}
One annoying thing with this implementation is that you have no way of knowing when your list of images has finished loading; Image.prefetch doesn't have a callback to help you here.
I'm using the code from the official site, and I am consistently seeing the same behavior on multiple test devices - instead of getting the current location of the device, it gets the previous location (up to 30 miles away, where I was an hour ago).
private void setupMaps()
{
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
watcher.MovementThreshold = 10.0f;
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_statusChanged);
watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
new Thread(startLocServInBackground).Start();
}
void startLocServInBackground()
{
watcher.TryStart(true, TimeSpan.FromSeconds(60));
}
void watcher_statusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
// The Location Service is disabled or unsupported.
// Check to see if the user has disabled the location service.
if (watcher.Permission == GeoPositionPermission.Denied)
{
// the user has disabled LocServ on their device.
showMessage("Location is required but it is disabled. Turn it on in Settings");
}
else
{
showMessage("Location is not functioning on this phone. Sorry, Crux cannot run");
}
break;
case GeoPositionStatus.Initializing:
// The location service is initializing.
LoadingInfo.Text = "finding location";
break;
case GeoPositionStatus.NoData:
// The Location Service is working, but it cannot get location data
// due to poor signal fidelity (most likely)
// this fired intermittently when data was coming back :/
//MessageBox.Show("Location data is not available.");
break;
case GeoPositionStatus.Ready:
// The location service is working and is receiving location data.
//statusTextBlock.Text = "Location data is available.";
LoadingInfo.Text = "Location found";
// THIS FIRES AFTER POSITION CHANGED HAS STOPPED FIRING
break;
}
}
private void initPostPanel()
{
PostPanel.Visibility = Visibility.Visible;
}
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
// update the textblock readouts.
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
// THIS FIRES TWICE, BEFORE STATUS IS FIRED AS READY. THEN THIS DOESN'T CALL AGAIN
}
What I would expect to have happen is to get a continuous series of calls to PositionChanged after StatusChanged is called with a Status of Ready. If the calls continued after Ready, I expect I would eventually get the correct coordinates - but it never calls after that point.
This does not occur with the emulator, only on the actual device (making this extremely difficult to test - since it actually involves driving between each test!)
I am running the source code from the tutorial as well, and it does roughly the same.
Can anyone tell me more about the expected behavior here and how I get what I need - which is simply a set of coordinates for the device at the current location when the app is being used.
I had the same problem myself - there are 2 parts to this.
Turns out the GeoCoordinateWatcher returns the last known good position - which is almost always out of date. What I do is something like this:
Check that the status is GeoPositionStatus.Ready and then ensure the datetime of the position is recent (within the last 5 mins). You can then go further and check that e.Position.Location.HorizontalAccuracy <= 350 (so under 350m) - but doing this with the datetime check as well can cause the phone to take a long time to get a position the lower you set the accuracy, so it may be best to get an initial position with the date check, and then continue to try get a better position with the Accuracy check. I also start the watcher as soon as the app starts to get faster results.
The other issue is MovementThreshold. If you do as I said above, it might still take a while before you get an accurate position, and you will likely experience the intermittent problem you mentioned where it does not fire the 2nd time (it does eventually, depending how long you wait - this can be minutes). The best thing I have found is to start the GeoCoordinateWatcher with the threshold set to 0. Once you have got an accurate position, stop the watcher, set the threshold to the actual one you want (eg 10), and then start it again. If you set this without stopping first, it will not use the new value.
<!-- language: c# -->
GeoPositionStatus = CurrentGeoDeviceStatus;
static void geoCoordWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
CurrentGeoDeviceStatus = e.Status;
}
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
if (gpsReady && e.Position.Timestamp.DateTime.AddMinutes(5) > DateTime.Now)
{
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
locReady = true;
}
}
It looks like the fix was to block it from using the first value and getting it from the second event instead:
bool gpsReady = false;
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
if (gpsReady)
{
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
locReady = true;
}
gpsReady = true;
}
I'm still baffled about why I don't get more events or why it fires an incorrect value first, but the above code seems to be working.
One note, for anyone else trying this, is that you might think getting the value in the StatusChanged event would work, like so:
case GeoPositionStatus.Ready:
latitude = watcher.Position.Location.Latitude.ToString("0.0000000000");
longitude = watcher.Position.Location.Longitude.ToString("0.0000000000");
break;
I don't know why, but the above code seemed to work perfectly when I was running attached to the debugger and then frequently hung (that is, the event never fired and my UI seemed to hang) in practical use. I never managed to reproduced the issue while attached to the debugger.
UPDATE: It looks like this isn't working all of the time. In some cases it doesn't fire the second time and so my code never completes running. If anyone can provide more information around this that gets me closer to simply having the actual current location of the device without fail, I will definitely mark your answer as the answer. Thanks!