about summary refs log tree commit diff
path: root/converter/other/cameratopam/ljpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/cameratopam/ljpeg.c')
-rw-r--r--converter/other/cameratopam/ljpeg.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/converter/other/cameratopam/ljpeg.c b/converter/other/cameratopam/ljpeg.c
new file mode 100644
index 00000000..18423f4f
--- /dev/null
+++ b/converter/other/cameratopam/ljpeg.c
@@ -0,0 +1,141 @@
+#define _BSD_SOURCE    /* Make sure string.h containst strcasecmp() */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "pm.h"
+
+#include "global_variables.h"
+#include "util.h"
+#include "decode.h"
+#include "bayer.h"
+
+#include "ljpeg.h"
+
+
+/*
+   Not a full implementation of Lossless JPEG, just
+   enough to decode Canon, Kodak and Adobe DNG images.
+ */
+
+int  
+ljpeg_start (FILE * ifp, struct jhead *jh)
+{
+  int i, tag, len;
+  unsigned char data[256], *dp;
+
+  init_decoder();
+  for (i=0; i < 4; i++)
+    jh->huff[i] = free_decode;
+  fread (data, 2, 1, ifp);
+  if (data[0] != 0xff || data[1] != 0xd8) return 0;
+  do {
+    fread (data, 2, 2, ifp);
+    tag =  data[0] << 8 | data[1];
+    len = (data[2] << 8 | data[3]) - 2;
+    if (tag <= 0xff00 || len > 255) return 0;
+    fread (data, 1, len, ifp);
+    switch (tag) {
+      case 0xffc3:
+    jh->bits = data[0];
+    jh->high = data[1] << 8 | data[2];
+    jh->wide = data[3] << 8 | data[4];
+    jh->clrs = data[5];
+    break;
+      case 0xffc4:
+    for (dp = data; dp < data+len && *dp < 4; ) {
+      jh->huff[*dp] = free_decode;
+      dp = make_decoder (++dp, 0);
+    }
+    }
+  } while (tag != 0xffda);
+  jh->row = calloc (jh->wide*jh->clrs, 2);
+  if (jh->row == NULL)
+      pm_error("Out of memory in ljpeg_start()");
+  for (i=0; i < 4; i++)
+    jh->vpred[i] = 1 << (jh->bits-1);
+  zero_after_ff = 1;
+  getbits(ifp, -1);
+  return 1;
+}
+
+int 
+ljpeg_diff (struct decode *dindex)
+{
+  int len, diff;
+
+  while (dindex->branch[0])
+    dindex = dindex->branch[getbits(ifp, 1)];
+  diff = getbits(ifp, len = dindex->leaf);
+  if ((diff & (1 << (len-1))) == 0)
+    diff -= (1 << len) - 1;
+  return diff;
+}
+
+void
+ljpeg_row (struct jhead *jh)
+{
+  int col, c, diff;
+  unsigned short *outp=jh->row;
+
+  for (col=0; col < jh->wide; col++)
+    for (c=0; c < jh->clrs; c++) {
+      diff = ljpeg_diff (jh->huff[c]);
+      *outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff);
+      outp++;
+    }
+}
+
+void  
+lossless_jpeg_load_raw(void)
+{
+  int jwide, jrow, jcol, val, jidx, i, row, col;
+  struct jhead jh;
+  int min=INT_MAX;
+
+  if (!ljpeg_start (ifp, &jh)) return;
+  jwide = jh.wide * jh.clrs;
+
+  for (jrow=0; jrow < jh.high; jrow++) {
+    ljpeg_row (&jh);
+    for (jcol=0; jcol < jwide; jcol++) {
+      val = curve[jh.row[jcol]];
+      jidx = jrow*jwide + jcol;
+      if (raw_width == 5108) {
+    i = jidx / (1680*jh.high);
+    if (i < 2) {
+      row = jidx / 1680 % jh.high;
+      col = jidx % 1680 + i*1680;
+    } else {
+      jidx -= 2*1680*jh.high;
+      row = jidx / 1748;
+      col = jidx % 1748 + 2*1680;
+    }
+      } else if (raw_width == 3516) {
+    row = jidx / 1758;
+    col = jidx % 1758;
+    if (row >= raw_height) {
+      row -= raw_height;
+      col += 1758;
+    }
+      } else {
+    row = jidx / raw_width;
+    col = jidx % raw_width;
+      }
+      if ((unsigned) (row-top_margin) >= height) continue;
+      if ((unsigned) (col-left_margin) < width) {
+    BAYER(row-top_margin,col-left_margin) = val;
+    if (min > val) min = val;
+      } else
+    black += val;
+    }
+  }
+  free (jh.row);
+  if (raw_width > width)
+    black /= (raw_width - width) * height;
+  if (!strcasecmp(make,"KODAK"))
+    black = min;
+}
+
+