#!/usr/local/bin/octave-cli -q

if (nargin < 1 || nargin > 4)
    error([
        "\tExpecting image file name as first argument,\n",
        "\toptional interpolation method as second argument and\n",
        "\toptional max and min values as third and fourth arguments\n"
    ]); 
endif

global rowsR;  global colsR;
global rowsG1; global colsG1;
global rowsG2; global colsG2;
global rowsB;  global colsB;

########################################################################
# Panasonic RAW 3 raws
# Expecting:
#  G1|R |G1
#  --+--+--
#  B |G2|B 
#  --+--+--
#  G1|R |G1
########################################################################
function panasonicRAW3(w,h)
    global  rowsR;      global colsR;
    global  rowsG1;     global colsG1;
    global  rowsG2;     global colsG2;
    global  rowsB;      global colsB;
    rowsG1 = [0:1:uint16(h/2)-1].*2.+1;
    colsG1 = [0:1:uint16(w/2)-1].*2.+1;
    rowsR  = rowsG1;    colsR  = colsG1.+1;
    colsR  = colsR(find(colsR<=w));
    rowsG2 = rowsG1.+1; colsG2 = colsR;
    rowsG2 = rowsG2(find(rowsG2<=h));
    rowsB  = rowsG2;    colsB  = colsG1;
endfunction

########################################################################
# Canon CR2 raws
# Expecting:
#  R |G1|R
#  --+--+--
#  G2|B |G2
#  --+--+--
#  R |G1|R
########################################################################
function canonCR2(w,h)
    global  rowsR;      global colsR;
    global  rowsG1;     global colsG1;
    global  rowsG2;     global colsG2;
    global  rowsB;      global colsB;
    rowsR  = [0:1:uint16(h/2)-1].*2.+1;
    colsR  = [0:1:uint16(w/2)-1].*2.+1;
    rowsG1 = rowsR;     colsG1 = colsR.+1;
    colsG1 = colsG1(find(colsG1<=w));
    rowsG2 = rowsR.+1;  colsG2 = colsR;
    rowsG2 = rowsG2(find(rowsG2<=h));
    rowsB  = rowsG2;    colsB  = colsG1;
endfunction

arg_list = argv();
info = imfinfo(arg_list{1});
fprintf(
    stderr, 
    "Image '%s' is %dx%d %dbpc %s %s\n", 
    info.Filename, 
    info.Width, info.Height, 
    info.BitDepth, info.ColorType, 
    info.Format
);
if (info.BitDepth != 16 
    || !(strcmp(info.ColorType, "grayscale") 
         || strcmp(info.ColorType, "indexed")))
    error("Expecting 16 bits per channel grayscale image\n"); 
endif

imethod = "spline";
M = 65535;
m = 0;

if (nargin >= 2)
    imethod = arg_list{2};
endif
if (nargin >= 3)
    M = sscanf(arg_list{3},"%d");
endif
if (nargin == 4)
    m = sscanf(arg_list{4},"%d");
endif
fprintf(stderr, "Interpolation: %s; Max: %d; Min: %d\n", imethod, M, m);

M = 65535 / (M - m);

img = imread(info.Filename);
#canonCR2(info.Width,info.Height);
panasonicRAW3(info.Width,info.Height);
imgR =  img(rowsR,  colsR);
printf("R:  min=%d;\tmax=%d\n", min(min(imgR)), max(max(imgR)));
imgG1 = img(rowsG1, colsG1);
printf("G1: min=%d;\tmax=%d\n", min(min(imgG1)), max(max(imgG1)));
imgG2 = img(rowsG2, colsG2);
printf("G2: min=%d;\tmax=%d\n", min(min(imgG2)), max(max(imgG2)));
imgB =  img(rowsB,  colsB);
printf("B:  min=%d;\tmax=%d\n", min(min(imgB)), max(max(imgB)));
img = [];
if (!strcmp(imethod, "none"))
    colsI = [3:info.Width-2];
    rowsI = [3:info.Height-2]';
    #colsI = [1:info.Width];
    #rowsI = [1:info.Height]';
    imgR =  interp2(colsR,  rowsR,  imgR,  colsI,  rowsI, imethod);
    imgG1 = interp2(colsG1, rowsG1, imgG1, colsI,  rowsI, imethod);
    imgG2 = interp2(colsG2, rowsG2, imgG2, colsI,  rowsI, imethod);
    imgB =  interp2(colsB,  rowsB,  imgB,  colsI,  rowsI, imethod);
    colsI = []; rowsI  = [];
endif
colsR  = []; rowsR  = [];
colsG1 = []; rowsG1 = [];
colsG2 = []; rowsG2 = [];
colsB  = []; rowsB  = [];
imgR =  uint16((imgR  .- m) .* M);
imgG1 = uint16((imgG1 .- m) .* M);
imgG2 = uint16((imgG2 .- m) .* M);
imgB =  uint16((imgB  .- m) .* M);

[dir, file, ext] = fileparts(info.Filename);
imwrite(imgR,  fullfile(dir, [file, "-r",  ".tiff"])); imgR  = [];
imwrite(imgG1, fullfile(dir, [file, "-g1", ".tiff"])); imgG1 = [];
imwrite(imgG2, fullfile(dir, [file, "-g2", ".tiff"])); imgG2 = [];
imwrite(imgB,  fullfile(dir, [file, "-b",  ".tiff"])); imgB  = [];
