[deprecated] MLV Viewer to view .mlv (and .raw) files on windows (C#)

Started by g3gg0, September 22, 2013, 01:25:04 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

tecgen

Hi g3gg0,

Quote...it uses nothing windows-specific, so it should run on any OS using mono.

I just want you to know, I tried to start the application with the latest mono version from www.go-mono.com on OSX 10.8.4. It hangs and no window is visible.

On OSX 10.8.4 you need to install mono (www.go-mono.com) and (http://xquartz.macosforge.org/trac/wiki). After the installation, you need to log off and log in again. Then start XQuartz and inside the application xterm. In the terminal (xterm) go to the path where you've downloaded g3gg0's application and type mono mlv_view_sharp.exe. Now the window of the MLV Viewer should appear.

best regards,
Marco
Canon 5D Mark II, 50D, 550D/Rebel T2i, EF 40mm f/2.8 STM, Sigma 18-35mm f/1.8, EF 85 f1.8, EF 135 f2.8 SF, Zoom H2n

escho

https://sternenkarten.com/
600D, 6D, openSUSE Tumbleweed

reddeercity

Just notice about the viewer and boy it sure save me a-lot of time.
Ran it under Windows 2008 Server R2 Enterprise, (it my PC Video Workstation)
Works very well, had  raw file on a Esata Drive viewed files @ 1/2 resolutions.
then converted the files i wanted to use. I used the first version of raw.
I had 160 GB to review.
That's a Must have tool !
thanks g3gg0, For the MLV viewer  :D

g3gg0

Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

Levinson

Excellent - thank you G3gg0!  :)

would it be too much to ask for a way to lock the exposure?

regards

Lev
5d3, 5d2 & 550d

escho

Quote from: Levinson on November 02, 2013, 07:39:40 AM

would it be too much to ask for a way to lock the exposure?


That would be fine, indeed. Maybe even with a little slider for manual exposure  :)
I would love such a possibility, because I cannot use mlv_viewer for my recordings of the moon and of the planets (jupiter or saturn) And viewing recordings of the ISS needs a locked exposure too.

Edgar
https://sternenkarten.com/
600D, 6D, openSUSE Tumbleweed

g3gg0

Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

g3gg0

updated: http://upload.g3gg0.de/pub_files/22126d3d0d9320097882049969b81de4/MLVViewSharp.exe

on the right you can choose exposure. center position is for auto-exposure (see tooltip when scrolling).
this is not lightroom where you can expect 99.99% exact results, but i hope i didnt do it totally wrong.

can you check if my EV correction is correct or at least close to reality?


btw, you can now drag MLV files onto the program icon to start and play back directly.
it will also most likely work as default application now.
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

maxotics

Hi g3gg0.  Again, thanks for making public your MLV viewer.  I'm running up against a problem that I hope you can help me with.

How are RAW pixel values saved to the RAW binary stream in the camera?  How can we read/write them?

I'm using this code of your to get pixel values from the RAW data.  The comments are mine.  However, I get lost in all the bit-wise arithmetic.


private unsafe static ushort BitExtract(byte* src, int offset, int position, int depth)
        {
           
            // src is a frame
            // offset is starts as 0, but is incremented by pitch 2,240 after every line of x's
            // int position is x
            // depth is usually 14

            // bpp could easily be hardcoded in function at 14bits
            // BitExtract(byte* src, int offset, int position, int depth)
            // dest[y, x] = BitExtract(pSrc, pos, x, bpp);

            // let's pretend x is 5, which would start it in the 5 x 14 = 70th bit or (8.75) 9th byte
            int value = 0;
            int src_pos = position * depth / 16; // or 5 * 14 / 16 = 4.37
            // bits_to_left = ((14 * 5) - (16 * 4.37)) % 16 =
            // 70 - 29.92 = .08
            int bits_to_left = ((depth * position) - (16 * src_pos)) % 16;
            // 16 - 14 - 0 = 2
            int shift_right = 16 - depth - bits_to_left;

            // 0 + 2 * 4.37 = 8.74
            int byteNum = offset + 2 * src_pos;

            // src[8] OR src[9]
            value = (int)src[byteNum] | (((int)src[byteNum + 1]) << 8);

            if (shift_right >= 0)
            {
                value >>= shift_right;
            }
            else
            {
                int val2 = (int)src[byteNum + 2] | (((int)src[byteNum + 3]) << 8);

                value <<= -shift_right;
                value |= val2 >> (16 + shift_right);
            }

            value &= (1 << depth) - 1;

            return (ushort)value;
        }



To write pixel values back I created this, which may be slow, but I can understand it.  I assumed, which is not working ;) for me, that I could just write each pixel's 14-bit value into the binary stream sequentially.  A1ex has tried to help me, but I just don't get it.  How you can pad anything and not run over the buffer.


// We want frame size * 14 bits bit array
                // First create boolean template for our bitarray
                bool[] framebool = new bool[Footer.xRes * Footer.yRes * 14];
                // Create BitArray from the array.
            BitArray framebits = new BitArray(framebool);
               
                int frameBitCount = 0;
                //int pixelbitpos = 0;

                // Not replace these bits with each of our 14 bit raw pixel values
                for (int x = 0; x < Footer.xRes; x ++)
                {
                    for (int y = 0; y < Footer.yRes; y++)
                    {
                        // convert our pixel value to a bitarray representation of 0s and 1s
                        //BitArray b = new BitArray(14); //
                        // We only want the 14bits, so create 14bit container

                        //pixelbitpos = 0; // will represent each of 14 bits of number that we write
                        string s = Convert.ToString((ushort)PixelData[y, x], 2);
                        s = s.PadLeft(14, '0');
                        //bool[] bits = new bool[14];

                        for (int bt = 0; bt < 14; bt++)
                        {
                            if (s[bt] == '1')
                            {
                                framebits[frameBitCount] = true;
                            }
                            else
                            {
                                framebits[frameBitCount] = false;
                            }
                            frameBitCount++; // advance to next bit in frame
                        }
                       
                        //bits.Reverse(); // may need
                    }
                }

                // We now need to write all the bits of our frame into bytes
                byte[] framebytes = new byte[framebits.Length / 8]; // + (framebits.Length % 8 == 0 ? 0 : 1)];
                framebits.CopyTo(framebytes,0);
               
                                // and write that frame into our copy of the RAW file
                // and shot that frame
                FileStream writeStream = File.OpenWrite(FileName.ToLower().Replace(".raw", "nodots.raw"));
                BinaryWriter writer = new BinaryWriter(writeStream);



Any help would be greatly appreciated and I'm sure it would help anyone else trying to get involved in this stuff.  THANKS!

escho

Can someone make this thread sticky, please?

Edgar

edit:
manual exposure works fine. ThankYou for adding.

Edgar
https://sternenkarten.com/
600D, 6D, openSUSE Tumbleweed

g3gg0

http://upload.g3gg0.de/pub_files/5e4147a7af9aa0191050fcf828a05c04/MLVViewSharp.exe

it has a white balancing feature:
- press and hold SHIFT
- press LEFT mouse button
- image will get displayed 1:1
- move to where you have gray level
- release LEFT mouse button
it will pick a 8x8 pixel area and use this as white balance reference.
known bug: when switching between debayer algorithms, you will have a green cast - just set WB again.

camera color matrices are also used now, which should result in better colors

to disable all correction post processing:
- right click to get context menu
- there is an option to disable color correction
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!


RenatoPhoto

Quote from: g3gg0 on November 04, 2013, 01:31:43 AM
known bug: when switching between debayer algorithms, you will have a green cast - just set WB again.
Or select that same algorithm and the color will be corrected... Double selection cures the bug.
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

g3gg0

fixed some weird behavior regarding color correction and added simple highlight recovery. (non-linear colorspace mapping)
a bit slower, but you can disable it via right clicking.
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

g3gg0

Quote from: maxotics on November 02, 2013, 05:10:25 PM
Any help would be greatly appreciated and I'm sure it would help anyone else trying to get involved in this stuff.  THANKS!
i am not sure what i could help there.
you want a function to write back pixels in the raw data?
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

maxotics

Quote from: g3gg0 on November 05, 2013, 01:19:55 AM
i am not sure what i could help there.
you want a function to write back pixels in the raw data?

EDIT: Okay, finally got it working.  If you swap each byte, so it's 2,1,4,3,6,5 and read each 14bits you'll get each x,y value.  I'll post code later.  What I didn't realize is I was cycling x within y, instead of y within x.  Not knowing the expected format made debugging that a nightmare.

g3gg0

Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

maxotics

Hi g3gg0.  The Kelvin thing looks complex indeed.  Do you think the quality of the debayering is good in the MLV viewer, or needs to be fast and rough?  Are you planning on putting in any other debayering algos?  I ask because I'm going to try to take a feed from the viewer and create video from it.  I have it working now where I can write pixel data back to the RAW file. So again, thanks for posting the MLV viewer. 

I'm going to post a thread on this whole RAW pixel data subject, so the next guy doesn't go through what I went through.  Here is the code if you're curious.  At some point I hope to write a sister reader version, just for ease of use. 


// We want frame size * 14 bits bit array
                // First create boolean template for our bitarray
                bool[] framebool = new bool[(Footer.xRes * Footer.yRes * 14)];
                // Create BitArray from the array.
            BitArray framebits = new BitArray(framebool);
               
                int frameBitCount = 0;
               
                // For swaping bytes
                bool[] bitsbyte1 = new bool[8];

                // Not replace these bits with each of our 14 bit raw pixel values
                for (int y = 0; y < Footer.yRes; y ++)
                {
                    for (int x = 0; x < Footer.xRes; x++)
                    {
                        string s = Convert.ToString((ushort)PixelData[y, x], 2);
                        s = s.PadLeft(14, '0');

                        for (int bt = 0; bt < 14; bt++)
                        {
                            if (s[bt] == '1')
                            {
                                framebits[frameBitCount] = true;
                            }
                            else
                            {
                                framebits[frameBitCount] = false;
                            }
                         frameBitCount++; // advance to next bit in frame
                        }
                    }
                }

                // now swap each bye
                for (int s = 0; s < framebits.Length; s += 16)
                {
                    // save first byte
                    bitsbyte1[0] = framebits[s];
                    bitsbyte1[1] = framebits[s+1];
                    bitsbyte1[2] = framebits[s+2];
                    bitsbyte1[3] = framebits[s+3];
                    bitsbyte1[4] = framebits[s+4];
                    bitsbyte1[5] = framebits[s+5];
                    bitsbyte1[6] = framebits[s+6];
                    bitsbyte1[7] = framebits[s+7];

                    // Now swap second into first (odd)
                    framebits[s] = framebits[s + 15];
                    framebits[s + 1] = framebits[s + 14];
                    framebits[s + 2] = framebits[s + 13];
                    framebits[s + 3] = framebits[s + 12];
                    framebits[s + 4] = framebits[s + 11];
                    framebits[s + 5] = framebits[s + 10];
                    framebits[s + 6] = framebits[s + 9];
                    framebits[s + 7] = framebits[s + 8];
                   
                    // now write our save first byte into second (even)
                    framebits[s + 8] = bitsbyte1[7];
                    framebits[s + 9] = bitsbyte1[6];
                    framebits[s + 10] = bitsbyte1[5];
                    framebits[s + 11] = bitsbyte1[4];
                    framebits[s + 12] = bitsbyte1[3];
                    framebits[s + 13] = bitsbyte1[2];
                    framebits[s + 14] = bitsbyte1[1];
                    framebits[s + 15] = bitsbyte1[0];
                }

                // We now need to write all the bits of our frame into bytes
                byte[] framebytes = new byte[framebits.Length / 8 + (framebits.Length % 8 == 0 ? 0 : 1)];
                framebits.CopyTo(framebytes, 0);

                WriterTarget.BaseStream.Seek(Footer.frameSize * iFrameNumber, SeekOrigin.Begin);
                WriterTarget.Write(framebytes);


ted ramasola

Very nice improvement on the kelvin adjustments. Posting here to give thanks and to to track improvements.
5DmkII  / 7D
www.ramasolaproductions.com
Texas

RenatoPhoto

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

dsManning

Thank you so much :) Check focus from files off the card before dng conversion is such a time/space saver!

Got it running on my desktop workhorse running in parallels, and through mono on my 'in the field' laptop (a few years old and noticeably slower playback than my new Hackintosh desktop) but both are an amazing new tool to help optimize workflow.  Laptop on 1/4 with other features off is still good enough when scrubbing through to check for focus.  Desktop on 1/2 and messing with some colour features still plays back at a reasonable pace to give the thumbs up/down to a take.

g3gg0

here a comparison chart.

left side: monitor showing SMPTE test bars as jpeg in browser.
right side: mlv recorded with 5D3 and displayed with MLV viewer.

i think the color fits quite well :)

Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

pilgrim

It's work well on Windows 7 64bit.  :)  Now I can clean the hard disk from low rating RAW easily.  :D  Big thanks.

jose_ugs


arrinkiiii