Showing previously taken image on screen during long exposure

Started by dmilligan, September 05, 2013, 03:03:32 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

dmilligan

Think of it like this: extending Image Review into the time even after another exposure has started. This would be incredibly useful for astrophotography and night time lapses. Typically you are using the intervalometer and taking very long exposures 30s + with as little time between shots as possible (because clear dark sky time is very precious and rare, at least for me, and I want to spend absolutely every second of it I can collecting photons).  This basically means you get no or very very little time to review images after they are being taken before the screen blacks out and starts exposing again. There are all sorts of things that can go wrong while shooting astro (for example: dew, tracking error, focus) and it's very important to be able to keep an eye on what is going on.

It is possible to write to the screen during a bulb exposure, I have tried it (with text). First thing is disabling this very annoying line of code in shoot.c:

// for 550D and other cameras that may keep the display on during bulb exposures -> always turn it off
if (DISPLAY_IS_ON && s==1) fake_simple_button(BGMT_INFO);


BTW as a side note, I always have this line commented out for my own personal builds b/c I would much rather see the bulb time indication on the screen than save a little battery by turning the screen off. Batteries are cheap and sometimes I'm use an AC adapter anyway. When you're taking 5 to 10+ minute exposures, it's really nice to know how much time you have left.

So it seems very feasible to draw the most recently taken image to the screen during this time. I'm trying to figure out how to do this myself, but I'm not very familiar with the way the vram works and could use a few pointers (haha, pun intended). I've looked at the code for ghost image, and I see that it is basically going into play mode, capturing the vram and saving it to a file. Then it somehow writes that file over the lv display. I'm guessing that I could pretty much do something like that here: during the brief image review time in between shots, capture the vram buffer, then after the next shot starts exposing, restore it? I'm assuming I wouldn't really need to write to a file either, just copy it to somewhere in dynamic memory and then copy it back saving a lot of IO time.

I'm also a little nervous about just trying stuff and writing into these various buffers, which seems like it could be dangerous, esp. since I don't really know what they do or how they work.

dmilligan

Well, this got moved to feature requests, but clearly whoever moved it did not actually fully read my question. I realize that it started out sounding like a feature request, but I didn't really intended it to be one, really what I need is some help on how to capture and then later redisplay vram.

Anyways, I realized that while simply commenting out the line mentioned in the previous post was enough to leave the display on for my 1100D during a bulb exposure, on my 60D the canon firmware actually turns off the bulb display (apparently this is a canon 'feature' and the bulb time is only displayed on the top LCD, I assume all xxD and better cameras are like this since the have a top LCD and the xxxD cameras display it on the screen b/c there is no top LCD available). So I simply used display_on() to turn it back on. Here's a diff of the stuff I added to shoot.c in the bulb_take_pic function:


     
     int d0 = set_drive_single();
     //~ NotifyBox(3000, "BulbStart (%d)", duration); msleep(1000);
     mlu_lock_mirror_if_needed();
     
     SW1(1,300);
     
     int t_start = get_ms_clock_value();
     int t_end = t_start + duration;
     SW2(1,300);
     
     //~ msleep(duration);
     //int d = duration/1000;
     while (get_ms_clock_value() <= t_end - 1500)
     {
         msleep(100);

         // number of seconds that passed
         static int prev_s = 0;
         int s = (get_ms_clock_value() - t_start) / 1000;
         if (s == prev_s) continue;
         prev_s = s;
         
         // check the following at every second:
         
-        // for 550D and other cameras that may keep the display on during bulb exposures -> always turn it off
-        if (DISPLAY_IS_ON && s==1) fake_simple_button(BGMT_INFO);
-
+        // turn the display back on if it got turned off
+        if (s==1) display_on();
+       
+#ifdef FEATURE_INTERVALOMETER
+        if(intervalometer_running)
+        {
+            static char msg[60];
+            snprintf(msg, sizeof(msg),
+                     " Intervalometer: %s  \n"
+                     " Pictures taken: %d  ",
+                     format_time_hours_minutes_seconds(intervalometer_next_shot_time - seconds_clock),
+                     intervalometer_pictures_taken);
+            if (interval_stop_after) { STR_APPEND(msg, "/ %d", interval_stop_after); }
+            bmp_printf(FONT_LARGE, 50, 310, msg);
+        }
+#endif
+        NotifyBox(3000, "Remaining: %d", duration/1000 - s);
+       
         // tell how many minutes the exposure will take
         if (s == 2)
         {
             int d = duration / 1000;
             if (d/60) { beep_times(d/60); msleep(500); }
         }
         
         // turn off the LED - no light pollution, please :)
         // but blink it quickly every 10 seconds to have some feedback
         if (s % 10 == 1) { _card_led_on(); msleep(10); _card_led_off(); }

         // blink twice every minute, and beep as many times as elapsed minutes
         if (s % 60 == 1) { msleep(200); _card_led_on(); msleep(10); _card_led_off(); if (s/60) beep_times(s/60); }
         
         // exposure was canceled earlier by user
         if (job_state_ready_to_take_pic())
         {
             beep();
             break;
         }
     }
     
+    display_off();
+   
     while (get_ms_clock_value() < t_end && !job_state_ready_to_take_pic())
         msleep(MIN_MSLEEP);
     
     //~ NotifyBox(3000, "BulbEnd");
     
     SW2(0,0);
     SW1(0,0);
     
     lens_wait_readytotakepic(64);
     lens_cleanup_af();
     if (d0 >= 0) lens_set_drivemode(d0);
     prop_request_change( PROP_SHUTTER, &s0r, 4 );
     prop_request_change( PROP_SHUTTER_ALSO, &s0r, 4);
     set_shooting_mode(m0r);
     msleep(200);
     
     ml_taking_pic = 0;


I think this alone is quite a useful feature as it's possible to see the intervalometer info and time remaining for each bulb during the bulb exposure. The problem is that display_on() only works the first two times. This also seems to be independent of the intervalometer running. display_on() only works two times no matter what, until you turn the power off and back on.  Any ideas?

fpena06

I would love this feature! Def agree should be a feature request. Love the idea btw!

a1ex

display_on/off use low level diagnostic functions from Canon code. On 5D3 it seems reliable though (tried for 10 pictures and worked). Will try on 60D too, but it shouldn't be any different.

I prefer to leave the display off myself (not sure if the backlight can leak into the picture, but who knows).

Tip: here you can use bmp_printf instead of notify_box, because of less flicker. NotifyBox is intended for short notifications that last a few seconds (like the notifications from Ubuntu)

dmilligan

thanks for the tip, will do, I was just copy/pasting to try stuff

60D has articulated screen so I don't think light leaking should be an issue with it, esp. if you have it folded out. Personally, I'd rather have a little bit of light leak (and if you can't notice it does it really matter?), than realize the next morning that my lens fogged over 30 mins into a 4 hour timelapse, and I wasted 3 1/2 hours of precious clear dark sky time.


dmilligan

So I'm out here under the stars shooting right now and the screen is staying on more than just two times. I can't figure out what's going on with this b/c it never worked in my testing. Anyway I noticed that the background of th notify box is actually displaying the previously taken image, so I have a thin strip at least of what I want. Awesome. Now I just need to get the whole screen.


dmilligan

It works yay! All you have to do is clrcsr(); Thanks a1ex!


        if (s==1) display_on();
       
        clrscr();
        bmp_printf(FONT_LARGE,  50,  50, "Remaining: %d", duration/1000 - s);
#ifdef FEATURE_INTERVALOMETER
        if(intervalometer_running)
        {
            static char msg[60];
            snprintf(msg, sizeof(msg),
                     " Intervalometer: %s  \n"
                     " Pictures taken: %d  ",
                     format_time_hours_minutes_seconds(intervalometer_next_shot_time - seconds_clock),
                     intervalometer_pictures_taken);
            if (interval_stop_after) { STR_APPEND(msg, "/ %d", interval_stop_after); }
            bmp_printf(FONT_LARGE, 50, 310, msg);
        }
#endif

        // tell how many minutes the exposure will take
        if (s == 2)
        {
            int d = duration / 1000;
            if (d/60) { beep_times(d/60); msleep(500); }
        }


fpena06

Awesome! Do I need to change anything to try it on my 7D?

dmilligan

I don't think so. There are a couple of quirks though. display_on() only seems to work twice unless you have a bulb exposure longer than 30s (you may not have this issue on a 7D, IDK), and it only seems to start showing the picture after the 3rd exposure.

You can try it from here or just mod the shoot.c file yourself. I can send you an autoexec.bin if you'd like to try it and don't have the compiler set up.

fpena06

Quote from: dmilligan on September 10, 2013, 01:36:01 AM
You can try it from here or just mod the shoot.c file yourself. I can send you an autoexec.bin if you'd like to try it and don't have the compiler set up.

So I must compile a new autoexec.bin in order to get it working? I have a VMware machine with ubuntu and compiler setup. But I have only compiled https://bitbucket.org/OtherOnePercent/tragic-lantern-6d/commits/all How can I just add this feature to what I already have? Sorry still getting the hang of things.

Thanks!

dmilligan

mercurial probably has way to pull my changeset into your clone (local repo) of that fork, but I'm not that familiar with mercurial so I'm not sure how to do it. Probably easier to just manually modify your working copy of shoot.c. Just look at the diff on the commit page I linked to and modify those lines in your local working copy of shoot.c. Red means I deleted a line, green means I added one. (also don't actually put the + signs at the start of each line in your code, those are just part of the diff)

fpena06

Quote from: dmilligan on September 10, 2013, 02:10:29 AM
Probably easier to just manually modify your working copy of shoot.c. Just look at the diff on the commit page I linked to and modify those lines in your local working copy of shoot.c. Red means I deleted a line, green means I added one. (also don't actually put the + signs at the start of each line in your code, those are just part of the diff)

I'll give it a try.

Thanks!


fpena06

So I've made the changes and compiled a new autoexec.bin. I get time remaining, intervalometer and pictures taken. But the preview doesn't stay long enough. Btw after a few shots screen goes black and you could no longer see time remaining, intervalometer and pictures taken (intervalometer continues workingthough). I made sure bulb goes for atleast 35s since you specified it has to be longer than 30s also had intervalometer take atleast 10 photos.

Thanks.

dmilligan

Quote from: fpena06 on September 10, 2013, 04:41:37 AM
Btw after a few shots screen goes black and you could no longer see time remaining, intervalometer and pictures taken (intervalometer continues workingthough).

Yeah that's what I was talking about with display_on(), this happens to me too occasionally, it seems to mostly happen with shorter bulb exposures for me though. Canon is turning the screen off during the bulb exposure, so I'm using that function to try and turn it back on. Maybe try it a couple times with different bulb times, and see if you can get it to work. Make sure you turn the camera off and back on between each try. I've found that once display_on() stops working, it wont start working again till you turn the camera off and back on.

I'm going to try calling it at different times in the code to see if it will work more reliably. You could try this too, change the line if(s==1) to something like 2 or 3. Also try calling before the beginning of the while loop.

@a1ex,
perhaps this is a concurrency issue? is there a semaphore or lock I need to grab before calling this fuction? do you think there is some other task running during this time that could be interfering?

a1ex

Just merged it, and it's in the current nightly. I'd like to ask everybody to try it and check all modes on their camera.

5D3: all seems fine.
550D: can't show previous picture (screen remains black).

=> this trick is not fully portable, so I'd like to disable it where it doesn't work. Right now it's enabled on everything but 550D, but it's likely not to work on Rebel cameras (not yet sure).

@dmilligan: does it show the previous image on 1100D?

dmilligan


a1ex

Interesting, so it's likely to work on 600D too in this case.

Do you still get the erratic behavior after my changes?

RenatoPhoto

on 7D silent.mo does not work but this was the same with yesterdays build.
Linking:
tcc: error: undefined symbol "display_filter_get_buffers"

The actual test of the review image I am not sure how to test it... Do I test in B mode?  What settings to use?  I am not fully understanding how to enable the feature.
http://www.pululahuahostal.com  |  EF 300 f/4, EF 100-400 L, EF 180 L, EF-S 10-22, Samyang 14mm, Sigma 28mm EX DG, Sigma 8mm 1:3.5 EX DG, EF 50mm 1:1.8 II, EF 1.4X II, Kenko C-AF 2X

dmilligan

Canon > Bulb Mode

ML > Shoot > Bulb Timer > Display during exposure => set to 'Show previous pic'

Intended to be used with intervalometer, so turn it on.

The screen should come back on during the bulb exposure and show intervalometer status, time remaining and the previous pic (after the second picture)

RenatoPhoto

Tested with
7D
Intervalometer set at 10 s
Bulb timer at 10 and then at 9s
In canon menu review time at 8 sec

During intervalometer the previous image did not show on LV
On the first and second image there was information about count down and  intervalometer but did not show up again on consecutive images
The image never showed up
http://www.pululahuahostal.com  |  EF 300 f/4, EF 100-400 L, EF 180 L, EF-S 10-22, Samyang 14mm, Sigma 28mm EX DG, Sigma 8mm 1:3.5 EX DG, EF 50mm 1:1.8 II, EF 1.4X II, Kenko C-AF 2X

RenatoPhoto

Tested with 5D3
Same settings

First run..
The image shows only once after the first image is taken
The second image and thereafter are never shown

Should I try a different setting?
http://www.pululahuahostal.com  |  EF 300 f/4, EF 100-400 L, EF 180 L, EF-S 10-22, Samyang 14mm, Sigma 28mm EX DG, Sigma 8mm 1:3.5 EX DG, EF 50mm 1:1.8 II, EF 1.4X II, Kenko C-AF 2X

dmilligan

try longer than 30s bulb, and/or more time between pictures

RenatoPhoto

Intervalometer 1 min
Bulb 45 sec
Canon Review 8 sec

7D:
Only shows image during the Canon review time after photo is taken and nothing after second image is being taken.

5D3:
Shows image during the Canon review time  (8sec) after photo is taken and also during time second image being taken.  After that it only shows during the 8 sec review time right after the image is take and before the intervalometer  starts taking the next image.

In my opinion the review time should never be longer than a few seconds so will you want to review the image during the next x seconds that the next photo is being taken.. Will wear out my battery really quick....

http://www.pululahuahostal.com  |  EF 300 f/4, EF 100-400 L, EF 180 L, EF-S 10-22, Samyang 14mm, Sigma 28mm EX DG, Sigma 8mm 1:3.5 EX DG, EF 50mm 1:1.8 II, EF 1.4X II, Kenko C-AF 2X