#include <u.h>
#include <libc.h>
#include <bio.h>
#include <tiff.h>
static int
lg2(ulong i)
{
int j;
for(j = 0; (i >>= 1) != 0; j++)
;
return j;
}
static ulong
genmsk(ulong n)
{
ulong i;
for(i = 0; n; n--)
i = i<<1 | 1;
return i;
}
static int
expand(Tiff *t, ulong i, ulong o)
{
uchar *p, *e, *s, *op;
ulong scale, mask, bits, nbits, shift, r, rb;
long l;
int c;
shift = lg2(o/i);
l = tiffimglen(t)<<shift;
s = malloc(l+4);
if(!s)
return -1;
p = t->rawimg;
e = t->rawimge;
bits = 0;
nbits = 0;
r = 0;
rb = 0;
mask = genmsk(i);
scale = genmsk(o)/mask;
for(op = s; op < s+l; ){
while(nbits < i){
if(p >= e)
sysfatal("p>e %uld %uld", (ulong)p, (ulong)e); //goto bad;
c = *p++;
bits = bits<<8|c;
nbits += 8;
}
if(nbits<i)
break;
while(nbits >= i){
nbits -= i;
r = r<<o | ((bits>>nbits)&mask)*scale;
rb += o;
while(rb >= 8){
rb -= 8;
*op++ = (r>>rb)&0xff;
r >>= 8;
}
}
bits &= mask; // delete used bits.
}
if(nbits != 0)
goto bad;
if(rb)
*op = r&0xff;
free(t->rawimg);
t->rawimg = s;
t->rawimge = s+l;
return l;
bad:
free(s);
return -1;
}
static int
chanokay(int n)
{
if(n==0 || (n>8 && n%8) || (n<8 && 8%n))
return 0;
return n;
}
static int
cdepthequal(Tiff *t){
IFD *cdepth;
int n, i;
cdepth = lookifdptr(t, Tbitspersample);
if(!cdepth)
return 0;
n = cdepth->sp[0];
for(i = 1; i < cdepth->n; i++)
if(cdepth->sp[i] != n)
return 0;
return n;
}
static int
setbitsps(Tiff *t, int o)
{
IFD *i;
int j;
i = lookifdptr(t, Tbitspersample);
if(!i)
return -1;
for(j = 0; j < i->n; j++)
i->sp[j] = o;
t->bpp = o*i->n;
return 0;
}
int
tiffexpand(Tiff *t)
{
int n, m, i;
if(chanokay(t->bpp))
return 0;
if((n = cdepthequal(t)) == 0)
return -1;
// number theory.
for(i = 1; i < 5; i++)
if(chanokay(3*(n+i)))
break;
if(i>5)
return -1;
m = n+i;
if(expand(t, n, m) == -1)
return -1;
if(setbitsps(t, m))
return -1;
return 0;
}
|