macro to read Canon viewport data

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

macro to read Canon viewport data

Jon Harman-3
Hi,

I have been having a great deal of fun with my new Canon A720IS.  Fun
mainly because of CHDK.  CHDK is a "firmware add-on for Canon's Digic II
& Digic III cameras": http://chdk.wikia.com/wiki/CHDK

Building on CHDK's code I wrote a routine to save the viewport data from
the camera.  The viewport is the image data that appears on the LCD
screen.  It is encoded in a YUV format.  See my post on the CHDK forum
for more info: http://chdk.setepontos.com/index.php/topic,1171.0.html

For CHDK developers I have written an ImageJ macro to display the
viewport data.  Thanks to Curtis it is now finished.  Here it is:

//This macro can read Canon viewport data and convert to RGB format.
//For my camera, the A720IS, the viewport data is 360x240 x 3bytes.
//Every 6 bytes in the data is encoded as U,Y1,V,Y2,Y3,Y4 in the YUV
color system.
//This routine decodes that into 4 RGB pixels.  So the output for my
camera is
//720x280.  The true aspect ratio is 360x240.


path = File.openDialog("Choose a File");
run("Raw...", "open=["+path+"] image=[24-bit RGB] width=360 height=240
offset=0 number=1 gap=0 little-endian");
setBatchMode(true);

id0 = getImageID();
width = getWidth();
height = getHeight();

line = newArray(width * 2);

newImage("Converted", "RGB", width * 2, height, 1);
id1 = getImageID();

for (h=0;h<height;h++) {
        w1 = 0;
        selectImage(id0);
        for(w=0;w<width;w+=2) {
          p = getPixel(w,h);
              u = (p>>16)&0xff;
                if ((u&0x80) != 0) u = u - 255 + 1;
              y = (p>>8)&0xff;
                v = p &0xff;
                if ((v&0x80) != 0)  v = 255-v + 1;
                r = clip(((y * 4096)          + v*5743 + 2048)/4096); // R    
                g = clip(((y * 4096) - u*1411 - v*2925 + 2048)/4096); // G
                b = clip(((y * 4096) + u*7258          + 2048)/4096); // B

                line[w1++] = (r << 16)  + (g << 8) + b;

                p = getPixel(w+1,h);

                y = (p>>16) & 0xff;
                y1 = (p>>8) & 0xff;
                y2 = p & 0xff;

                r = clip(((y1 * 4096)          + v*5743 + 2048)/4096); // R    
                g = clip(((y1 * 4096) - u*1411 - v*2925 + 2048)/4096); // G
                b = clip(((y1 * 4096) + u*7258          + 2048)/4096); // B

                line[w1++] = (r << 16)  + (g << 8) + b;

                r = clip(((y1 * 4096)          + v*5743 + 2048)/4096); // R    
                g = clip(((y1 * 4096) - u*1411 - v*2925 + 2048)/4096); // G
                b = clip(((y1 * 4096) + u*7258          + 2048)/4096); // B

                line[w1++] = (r << 16)  + (g << 8) + b;

                r = clip(((y2 * 4096)          + v*5743 + 2048)/4096); // R    
                g = clip(((y2 * 4096) - u*1411 - v*2925 + 2048)/4096); // G
                b = clip(((y2 * 4096) + u*7258          + 2048)/4096); // B

                line[w1++] = (r << 16)  + (g << 8) + b;
        }
       
        selectImage(id1);
        for(w=0;w<width * 2; w++) setPixel(w,h,line[w]);
}
setBatchMode(false);

    function clip(a) {
       if(a < 0) a = 0;
       if(a > 255) a = 255;
       return a;
    }