readtif: fix many bugs

totif: add tiff encoder
This commit is contained in:
ppatience0 2013-07-19 02:16:43 -04:00
parent 24a5720bec
commit 360cabb858
7 changed files with 1731 additions and 87 deletions

View file

@ -1,6 +1,6 @@
.TH JPG 1 .TH JPG 1
.SH NAME .SH NAME
jpg, gif, png, tif, ppm, bmp, v210, yuv, ico, tga, tojpg, togeordi, togif, toppm, topng, toico \- view and convert pictures jpg, gif, png, tif, ppm, bmp, v210, yuv, ico, tga, tojpg, togeordi, togif, toppm, topng, totif, toico \- view and convert pictures
.SH SYNOPSIS .SH SYNOPSIS
.B jpg .B jpg
[ [
@ -127,6 +127,16 @@ jpg, gif, png, tif, ppm, bmp, v210, yuv, ico, tga, tojpg, togeordi, togif, toppm
] [ ] [
.I file .I file
] ]
.br
.B totif
[
.B -c
.I comment
] [
.B -bBgGhHlLmprtT
] [
.I file
]
.PP .PP
.B ico .B ico
[ [
@ -157,9 +167,11 @@ to Plan 9 image format and write them to standard output.
.IR Tojpg , .IR Tojpg ,
.IR togif , .IR togif ,
.IR toppm , .IR toppm ,
.IR topng ,
and and
.I topng .I totif
read Plan 9 images files, convert them to JPEG, GIF, PPM, or PNG, and write them to standard output. read Plan 9 images files, convert them to JPEG, GIF, PPM,
PNG, or TIFF and write them to standard output.
.PP .PP
The default behavior of The default behavior of
.IR jpg , .IR jpg ,
@ -246,7 +258,7 @@ The
and and
.IR topng .IR topng
programs go the other way: they convert from Plan 9 images to JPEG, GIF, programs go the other way: they convert from Plan 9 images to JPEG, GIF,
PPM and PNG and have no display capability. PPM, PNG, and TIFF and have no display capability.
They all accept an option They all accept an option
.B -c .B -c
to set the comment field of the resulting file. to set the comment field of the resulting file.
@ -270,6 +282,52 @@ is an
script that invokes script that invokes
.B tojpg .B tojpg
.BR -s . .BR -s .
.I Totif
accepts many options.
Choosing Huffman, T4, or T6 compression
forces the output to be a bilevel image.
.TP
.B -b
Output a bilevel (GREY1) image.
.TP
.B -B
Output a grayscale (GREY2) image.
.TP
.B -g
Output a grayscale (GREY4) image.
.TP
.B -G
Output a grayscale (GREY8) image.
.TP
.B -h
Use Huffman compression.
.TP
.B -H
Use T4 one-dimensional compression.
.TP
.B -l
Use LZW compression.
.TP
.B -L
Use LZW compression with horizontal differencing.
Note that some TIFF decoders may not accept horizontal
differencing applied to images with depths less than eight.
.TP
.B -m
Output a color (CMAP8) image.
.TP
.B -p
Use Packbits compression.
.TP
.B -r
Output a color (BGR24) image.
.TP
.B -t
Use T4 two-dimensional compression.
.TP
.B -T
Use T6 compression.
.PP
If there is only one input picture, If there is only one input picture,
.I togif .I togif
converts the image to GIF format. converts the image to GIF format.

View file

@ -75,10 +75,12 @@ Memimage* memonechan(Memimage*);
char* writeppm(Biobuf*, Image*, char*, int); char* writeppm(Biobuf*, Image*, char*, int);
char* memwriteppm(Biobuf*, Memimage*, char*, int); char* memwriteppm(Biobuf*, Memimage*, char*, int);
char* writejpg(Biobuf*, Image*, char*, int, int);
char* memwritejpg(Biobuf*, Memimage*, char*, int, int);
Image* multichan(Image*); Image* multichan(Image*);
Memimage* memmultichan(Memimage*); Memimage* memmultichan(Memimage*);
char* memwritepng(Biobuf*, Memimage*, ImageInfo*); char* memwritepng(Biobuf*, Memimage*, ImageInfo*);
char* writejpg(Biobuf*, Image*, char*, int, int); char* writetif(Biobuf*, Image*, char*, int, int);
char* memwritejpg(Biobuf*, Memimage*, char*, int, int); char* memwritetif(Biobuf*, Memimage*, char*, int, int);

View file

@ -10,6 +10,7 @@ TARG=\
png\ png\
topng\ topng\
tif\ tif\
totif\
yuv\ yuv\
ico\ ico\
toico\ toico\
@ -54,9 +55,10 @@ $O.gif: $IMFILES readgif.$O gif.$O
$O.togif: writegif.$O onechan.$O togif.$O torgbv.$O $O.togif: writegif.$O onechan.$O togif.$O torgbv.$O
$O.ppm: $IMFILES readppm.$O ppm.$O $O.ppm: $IMFILES readppm.$O ppm.$O
$O.toppm: writeppm.$O multichan.$O toppm.$O $O.toppm: writeppm.$O multichan.$O toppm.$O
$O.png: $IMFILES readpng.$O png.$O $O.png: torgbv.$O writerawimage.$O readpng.$O png.$O
$O.topng: writepng.$O topng.$O $O.topng: writepng.$O topng.$O
$O.tif: $IMFILES readtif.$O tif.$O $O.tif: torgbv.$O writerawimage.$O readtif.$O tif.$O
$O.totif: writetif.$O totif.$O
$O.yuv: $IMFILES readyuv.$O yuv.$O $O.yuv: $IMFILES readyuv.$O yuv.$O
$O.bmp: $IMFILES readbmp.$O bmp.$O $O.bmp: $IMFILES readbmp.$O bmp.$O
$O.v210: $IMFILES readv210.$O v210.$O $O.v210: $IMFILES readv210.$O v210.$O

View file

@ -7,7 +7,7 @@
* http://www.itu.int/rec/T-REC-T.4-199904-S/en * http://www.itu.int/rec/T-REC-T.4-199904-S/en
* http://www.itu.int/rec/T-REC-T.6-198811-I/en * http://www.itu.int/rec/T-REC-T.6-198811-I/en
* *
* fax codes and lzw: * copy-pasted fax codes and lzw help:
* http://www.remotesensing.org/libtiff/ * http://www.remotesensing.org/libtiff/
*/ */
#include <u.h> #include <u.h>
@ -91,9 +91,10 @@ struct Fax {
Tab *tab[2]; Tab *tab[2];
int ntab; /* position in tab */ int ntab; /* position in tab */
Tab *eol; Tab *eol;
int eolfill;
int (*getbit)(Fax *); int (*getbit)(Fax *);
int *l1; ulong *l1;
int *l2; ulong *l2;
ulong nl; ulong nl;
uchar *data; uchar *data;
ulong next; /* next strip offset in data */ ulong next; /* next strip offset in data */
@ -433,7 +434,7 @@ static void fillbits(Fax *);
static int faxalloclines(Fax *); static int faxalloclines(Fax *);
static Tab *getfax1d(Fax *, uchar *, ulong, ulong *, ulong *, ulong); static Tab *getfax1d(Fax *, uchar *, ulong, ulong *, ulong *, ulong);
static Tab *getfax2d(Fax *, uchar *, ulong, ulong *, ulong *, ulong); static Tab *getfax2d(Fax *, uchar *, ulong, ulong *, ulong *, ulong);
static int faxstrip(Tif *, Fax *, uchar *, ulong, ulong *); static int faxstrip(Tif *, Fax *, uchar *, ulong, ulong, ulong *);
static uchar *fax(Tif *); static uchar *fax(Tif *);
static void tabinit(Lzw *); static void tabinit(Lzw *);
static Code *newcode(Lzw *, Code *); static Code *newcode(Lzw *, Code *);
@ -441,7 +442,8 @@ static void listadd(Lzw *, Code *);
static Code *tabadd(Lzw *, Code *, Code *); static Code *tabadd(Lzw *, Code *, Code *);
static int getcode(Lzw *); static int getcode(Lzw *);
static int wstr(uchar *, ulong, ulong *, Code *, long *); static int wstr(uchar *, ulong, ulong *, Code *, long *);
static void predict(Tif *, uchar *); static int predict1(Tif *, uchar *, ulong);
static int predict8(Tif *, uchar *, ulong);
static int lzwstrip(Lzw *, uchar *, ulong, ulong *, long); static int lzwstrip(Lzw *, uchar *, ulong, ulong *, long);
static uchar *lzw(Tif *); static uchar *lzw(Tif *);
static uchar *packbits(Tif *); static uchar *packbits(Tif *);
@ -669,6 +671,10 @@ geteol(Fax *f)
Tab *p; Tab *p;
if(f->eol == nil) { if(f->eol == nil) {
if(f->eolfill) {
for(i = 0; i < 4; i++)
(*f->getbit)(f);
}
if((p = gettab(f, 0)) == nil || p->run >= 0) { if((p = gettab(f, 0)) == nil || p->run >= 0) {
werrstr("first eol"); werrstr("first eol");
return nil; return nil;
@ -697,10 +703,8 @@ faxfill(Fax *f, uchar *data, ulong size, ulong *i, ulong *x, ulong dx,
werrstr("fax row overflow"); werrstr("fax row overflow");
return -1; return -1;
} }
if((*i += n) >= size) { if((*i += n) > size)
werrstr("fax data overflow");
return -1; return -1;
}
if(f->st != 0) if(f->st != 0)
memset(data+*i-n, f->st, n); memset(data+*i-n, f->st, n);
return 0; return 0;
@ -744,7 +748,7 @@ getfax1d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x,
int j, n; int j, n;
Tab *p; Tab *p;
for(j = 0; *x < dx;) { for(j = n = 0; *x < dx;) {
if((p = gettab(f, 0)) == nil) if((p = gettab(f, 0)) == nil)
return nil; return nil;
if((n = p->run) < 0) { if((n = p->run) < 0) {
@ -760,6 +764,17 @@ getfax1d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x,
if(j >= f->nl) if(j >= f->nl)
faxalloclines(f); faxalloclines(f);
} }
if(n >= 64) {
f->l1[j] = dx;
if((p = gettab(f, 0)) == nil)
return nil;
if((n = p->run) < 0)
return f->eol;
if(n != 0) {
werrstr("no terminating code");
return nil;
}
}
return nil; return nil;
} }
@ -767,7 +782,8 @@ static Tab *
getfax2d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x, getfax2d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x,
ulong dx) ulong dx)
{ {
int j, k, n, code, len, a0, a1, b1, b2, v; int j, k, n, code, len, v;
long a0, a1, b1, b2;
Tab *p; Tab *p;
a0 = -1; a0 = -1;
@ -795,7 +811,10 @@ getfax2d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x,
for(k = 0; k < 2;) { for(k = 0; k < 2;) {
if((p = gettab(f, 0)) == nil) if((p = gettab(f, 0)) == nil)
return nil; return nil;
n = p->run; if((n = p->run) < 0) {
werrstr("2d eol");
return nil;
}
if(faxfill(f, data, size, i, x, if(faxfill(f, data, size, i, x,
dx, n) < 0) dx, n) < 0)
return nil; return nil;
@ -842,7 +861,8 @@ getfax2d(Fax *f, uchar *data, ulong size, ulong *i, ulong *x,
} }
static int static int
faxstrip(Tif *t, Fax *f, uchar *data, ulong size, ulong *i) faxstrip(Tif *t, Fax *f, uchar *data, ulong size, ulong rows,
ulong *i)
{ {
int d1; int d1;
ulong x, y; ulong x, y;
@ -850,7 +870,7 @@ faxstrip(Tif *t, Fax *f, uchar *data, ulong size, ulong *i)
d1 = t->comp != T6enc; d1 = t->comp != T6enc;
p = nil; p = nil;
for(x = y = 0; x < t->dx || y < t->rows;) { for(x = y = 0; x < t->dx || y < rows;) {
f->st = 0; f->st = 0;
if(t->comp == T4enc) { if(t->comp == T4enc) {
if(p == nil && geteol(f) == nil) { if(p == nil && geteol(f) == nil) {
@ -858,8 +878,11 @@ faxstrip(Tif *t, Fax *f, uchar *data, ulong size, ulong *i)
return -1; return -1;
break; break;
} }
if(y > 0) if(y > 0) {
*i += t->dx - x; *i += t->dx - x;
if(*i > size)
break;
}
if(t->t4 & 1) { if(t->t4 & 1) {
d1 = (*f->getbit)(f); d1 = (*f->getbit)(f);
if(d1 < 0) if(d1 < 0)
@ -878,32 +901,34 @@ faxstrip(Tif *t, Fax *f, uchar *data, ulong size, ulong *i)
if(t->comp == Huffman) if(t->comp == Huffman)
fillbits(f); fillbits(f);
if(p == nil && x != t->dx) { if(p == nil && x != t->dx) {
if(f->st >= 0 || x > t->dx) if(f->st >= 0)
return -1;
if(x > t->dx)
return -1; return -1;
break; break;
} }
} }
if(*i > size) {
werrstr("fax data overflow");
return -1;
}
return 0; return 0;
} }
/* /* i've encountered t4 images that did not have rtcs */
* the t4 fax test images i decoded did not follow the
* spec. in particular, they did not have rtcs.
*/
static uchar * static uchar *
fax(Tif *t) fax(Tif *t)
{ {
int m; int m;
ulong i, j, datasz, linesz; ulong i, j, datasz, r, dy;
uchar *data; uchar *data;
Fax f; Fax f;
datasz = t->dx * t->dy * sizeof *data; datasz = t->dx * t->dy * sizeof *data;
data = malloc(datasz); data = mallocz(datasz, 1);
f.nl = t->dx; f.nl = t->dx + 1;
linesz = f.nl * sizeof *f.l1; f.l1 = mallocz(f.nl*sizeof *f.l1, 1);
f.l1 = malloc(linesz); f.l2 = mallocz(f.nl*sizeof *f.l2, 1);
f.l2 = malloc(linesz);
if(data == nil || f.l1 == nil || f.l2 == nil) { if(data == nil || f.l1 == nil || f.l2 == nil) {
free(t->data); free(t->data);
if(data != nil) if(data != nil)
@ -914,9 +939,6 @@ fax(Tif *t)
free(f.l2); free(f.l2);
return nil; return nil;
} }
memset(data, 0, datasz);
memset(f.l1, 0, linesz);
memset(f.l2, 0, linesz);
if(t->fill == 1) { if(t->fill == 1) {
f.getbit = getbit1; f.getbit = getbit1;
m = 7; m = 7;
@ -928,8 +950,12 @@ fax(Tif *t)
f.tab[1] = faxblack; f.tab[1] = faxblack;
f.ntab = 0; f.ntab = 0;
f.eol = nil; f.eol = nil;
if(t->comp == T4enc && t->t4 & (1<<1))
f.eolfill = 1;
else
f.eolfill = 0;
f.data = t->data; f.data = t->data;
for(i = j = 0; i < t->nstrips; i++) { for(i = j = 0, dy = t->dy; i < t->nstrips; i++) {
f.l1[0] = t->dx; f.l1[0] = t->dx;
f.n = t->strips[i]; f.n = t->strips[i];
f.m = m; f.m = m;
@ -937,8 +963,10 @@ fax(Tif *t)
f.next = t->strips[i+1]; f.next = t->strips[i+1];
else else
f.next = t->ndata; f.next = t->ndata;
if(faxstrip(t, &f, data, datasz, &j) < 0) r = dy < t->rows? dy: t->rows;
if(faxstrip(t, &f, data, datasz, r, &j) < 0)
break; break;
dy -= t->rows;
} }
if(i < t->nstrips) { if(i < t->nstrips) {
free(data); free(data);
@ -993,20 +1021,20 @@ tabadd(Lzw *l, Code *p, Code *q)
{ {
Code *r, *s; Code *r, *s;
if(l->ntab >= Tabsz) { r = s = &l->tab[l->ntab];
werrstr("lzw table full");
return nil;
}
r = s = &l->tab[l->ntab++];
switch(l->ntab) { switch(l->ntab) {
case 511: case 510:
case 1023: case 1022:
case 2047: case 2046:
l->len++; l->len++;
break; break;
default: default:
break; break;
} }
if(l->ntab++ >= Tabsz-3) {
werrstr("lzw table full");
return nil;
}
s->val = p->val; s->val = p->val;
while((p = p->next) != nil) { while((p = p->next) != nil) {
if(s->next != nil) if(s->next != nil)
@ -1033,6 +1061,7 @@ getcode(Lzw *l)
int i, c, code; int i, c, code;
if(l->n >= l->next) { if(l->n >= l->next) {
eof:
werrstr("lzw eof"); werrstr("lzw eof");
return -1; return -1;
} }
@ -1042,8 +1071,9 @@ getcode(Lzw *l)
code |= c << i; code |= c << i;
l->m--; l->m--;
if(l->m < 0) { if(l->m < 0) {
l->n++;
l->m = 7; l->m = 7;
if(++l->n >= l->next && i > 0)
goto eof;
} }
} }
return code; return code;
@ -1062,24 +1092,61 @@ wstr(uchar *data, ulong size, ulong *i, Code *p, long *striplen)
return 0; return 0;
} }
static void static int
predict(Tif *t, uchar *data) predict1(Tif *t, uchar *data, ulong ndata)
{
int bpl, pix, b[8], d, m, n, j;
ulong i, x, y;
bpl = bytesperline(Rect(0, 0, t->dx, t->dy), t->depth);
d = t->depth;
m = (1 << d) - 1;
n = 8 / d;
for(y = 0; y < t->dy; y++) {
for(x = 0; x < bpl; x++) {
i = y*bpl + x;
if(i >= ndata) {
werrstr("pred4 overflow");
return -1;
}
pix = data[i];
b[n-1] = (pix >> d*(n-1)) & m;
if(x > 0)
b[n-1] += data[i-1] & m;
for(j = n-2; j >= 0; j--) {
b[j] = (pix >> d*j) & m;
b[j] += b[j+1];
}
for(j = pix = 0; j < n; j++)
pix |= (b[j] & m) << d*j;
data[i] = pix;
}
}
return 0;
}
static int
predict8(Tif *t, uchar *data, ulong ndata)
{ {
char a, b; char a, b;
ulong y, x, i, j, k, s; ulong i, j, s, x, y;
s = t->samples; s = t->samples;
for(y = 0; y < t->dy; y++) { for(y = 0; y < t->dy; y++) {
for(x = 1; x < t->dx; x++) { for(x = 1; x < t->dx; x++) {
i = y*t->dx + x; i = (y*t->dx + x) * s;
for(j = 0; j < s; j++) { if(i+s-1 >= ndata) {
k = i*s + j; werrstr("pred8 overflow");
a = (char)data[k]; return -1;
b = (char)data[k-s]; }
data[k] = (uchar)(a + b); for(j = 0; j < s; i++, j++) {
a = (char)data[i];
b = (char)data[i-s];
data[i] = (uchar)(a + b);
} }
} }
} }
return 0;
} }
static int static int
@ -1102,6 +1169,10 @@ lzwstrip(Lzw *l, uchar *data, ulong size, ulong *i, long striplen)
break; break;
if(c < 0) if(c < 0)
return -1; return -1;
if(c >= l->ntab) {
werrstr("table overflow");
return -1;
}
if(wstr(data, size, i, &l->tab[c], if(wstr(data, size, i, &l->tab[c],
&striplen) < 0) &striplen) < 0)
return -1; return -1;
@ -1113,13 +1184,16 @@ lzwstrip(Lzw *l, uchar *data, ulong size, ulong *i, long striplen)
q = &l->tab[oc]; q = &l->tab[oc];
if(tabadd(l, q, p) == nil) if(tabadd(l, q, p) == nil)
return -1; return -1;
} else { } else if(c == l->ntab) {
q = &l->tab[oc]; q = &l->tab[oc];
if((p = tabadd(l, q, q)) == nil) if((p = tabadd(l, q, q)) == nil)
return -1; return -1;
if(wstr(data, size, i, p, if(wstr(data, size, i, p,
&striplen) < 0) &striplen) < 0)
return -1; return -1;
} else {
werrstr("table overflow");
return -1;
} }
if(striplen <= 0) if(striplen <= 0)
break; break;
@ -1132,15 +1206,16 @@ lzwstrip(Lzw *l, uchar *data, ulong size, ulong *i, long striplen)
static uchar * static uchar *
lzw(Tif *t) lzw(Tif *t)
{ {
ulong i, j, size; ulong i, j, size, r, dy, n;
long striplen; long striplen;
uchar *data; uchar *data;
Lzw l; Lzw l;
Code *p, *q; Code *p, *q;
int (*predict)(Tif *, uchar *, ulong);
i = t->dx * t->rows * t->depth; n = t->dx * t->dy * t->depth;
striplen = i%8 == 0? i/8: i/8+1; n = n%8 == 0? n/8: n/8+1;
size = t->nstrips * striplen * sizeof *data; size = n * sizeof *data;
if((data = malloc(size)) == nil) { if((data = malloc(size)) == nil) {
free(t->data); free(t->data);
return nil; return nil;
@ -1151,7 +1226,7 @@ lzw(Tif *t)
} }
l.data = t->data; l.data = t->data;
l.first = l.last = nil; l.first = l.last = nil;
for(i = j = 0; i < t->nstrips; i++) { for(i = j = 0, dy = t->dy; i < t->nstrips; i++) {
tabinit(&l); tabinit(&l);
l.n = t->strips[i]; l.n = t->strips[i];
l.m = 7; l.m = 7;
@ -1159,8 +1234,12 @@ lzw(Tif *t)
l.next = t->strips[i+1]; l.next = t->strips[i+1];
else else
l.next = t->ndata; l.next = t->ndata;
r = dy < t->rows? dy: t->rows;
n = t->dx * r * t->depth;
striplen = n%8 == 0? n/8: n/8+1;
if(lzwstrip(&l, data, size, &j, striplen) < 0) if(lzwstrip(&l, data, size, &j, striplen) < 0)
break; break;
dy -= t->rows;
} }
if(i < t->nstrips) { if(i < t->nstrips) {
free(data); free(data);
@ -1177,8 +1256,16 @@ lzw(Tif *t)
free(q); free(q);
} }
free(t->data); free(t->data);
if(data != nil && t->predictor == 2) if(data != nil && t->predictor == 2) {
predict(t, data); if(t->depth < 8)
predict = predict1;
else
predict = predict8;
if((*predict)(t, data, size) < 0) {
free(data);
return nil;
}
}
return data; return data;
} }
@ -1189,7 +1276,9 @@ packbits(Tif *t)
ulong i, j, k, size; ulong i, j, k, size;
uchar *data; uchar *data;
size = t->dx * t->dy * t->samples * sizeof *data; i = t->dx * t->dy * t->depth;
i = i%8 == 0? i/8: i/8+1;
size = i * sizeof *data;
if((data = malloc(size)) == nil) { if((data = malloc(size)) == nil) {
free(t->data); free(t->data);
return nil; return nil;
@ -1198,11 +1287,9 @@ packbits(Tif *t)
n = (char)t->data[i++]; n = (char)t->data[i++];
if(n >= 0) { if(n >= 0) {
k = n + 1; k = n + 1;
if(j+k >= size || i+k >= t->ndata) if((j += k) > size || (i += k) > t->ndata)
break; break;
memmove(data+j, t->data+i, k); memmove(data+j-k, t->data+i-k, k);
i += k;
j += k;
} else if(n > -128 && n < 0) { } else if(n > -128 && n < 0) {
k = j - n + 1; k = j - n + 1;
if(k > size || i >= t->ndata) if(k > size || i >= t->ndata)
@ -1461,18 +1548,18 @@ readfield(Tif *t, Fld *f)
size = typesizes[f->typ]; size = typesizes[f->typ];
if((n = size*f->cnt) <= 4) { if((n = size*f->cnt) <= 4) {
for(i = 0; i < f->cnt; i++) for(i = 0; i < f->cnt; i++)
f->val[i] = readval(t); f->val[i] = (*readval)(t);
f->off = 0x0; f->off = 0x0;
f->nval = i; f->nval = i;
for(j = n; j < 4; j += size) for(j = n; j < 4; j += size)
readval(t); (*readval)(t);
} else { } else {
f->off = readlong(t); f->off = readlong(t);
off = t->n; off = t->n;
if(gototif(t, f->off) < 0) if(gototif(t, f->off) < 0)
return -1; return -1;
for(i = 0; i < f->cnt; i++) for(i = 0; i < f->cnt; i++)
f->val[i] = readval(t); f->val[i] = (*readval)(t);
f->nval = i; f->nval = i;
if(gototif(t, off) < 0) if(gototif(t, off) < 0)
return -1; return -1;
@ -1600,10 +1687,6 @@ checkfields(Tif *t)
werrstr("color map"); werrstr("color map");
return -1; return -1;
} }
if(t->predictor == 2 && t->depth == 1) {
werrstr("depth too low for predictor 2");
return -1;
}
return 0; return 0;
} }
@ -1613,9 +1696,14 @@ readstrips(Tif *t)
int i, j, n; int i, j, n;
ulong off; ulong off;
t->data = nil;
t->ndata = 0; t->ndata = 0;
for(i = 0; i < t->nstrips; i++) for(i = 0; i < t->nstrips; i++)
t->ndata += t->counts[i]; t->ndata += t->counts[i];
if(t->ndata == 0) {
werrstr("no image data");
return -1;
}
if((t->data = malloc(t->ndata*sizeof *t->data)) == nil) if((t->data = malloc(t->ndata*sizeof *t->data)) == nil)
return -1; return -1;
off = t->n; off = t->n;

View file

@ -169,17 +169,15 @@ show(int fd, char *name, int outchan)
if(array == nil || array[0] == nil) { if(array == nil || array[0] == nil) {
if(array != nil) if(array != nil)
free(array); free(array);
fprint(2, "%s: decode %s failed: %r\n", argv0, fprint(2, "%s: decode %s failed: %r\n",
name); argv0, name);
return "decode"; return "decode";
} }
Bterm(&b); Bterm(&b);
if(!dflag) { if(!dflag) {
if(init() < 0) if(init() < 0)
return "initdraw"; return "initdraw";
/* fixme: ppm doesn't check for outchan==CMAP8 */ if(defaultcolor && screen->depth > 8)
if(defaultcolor && screen->depth > 8 &&
outchan == CMAP8)
outchan = RGB24; outchan = RGB24;
} }
r = array[0]; r = array[0];
@ -232,13 +230,11 @@ show(int fd, char *name, int outchan)
argv0, name); argv0, name);
return "write"; return "write";
} }
} else if(cflag) { } else if(cflag && writerawimage(1, c) < 0) {
if(writerawimage(1, c) < 0) {
fprint(2, "%s: %s: write error: %r\n", fprint(2, "%s: %s: write error: %r\n",
argv0, name); argv0, name);
return "write"; return "write";
} }
}
if(c != nil && c != r) { if(c != nil && c != r) {
free(c->chans[0]); free(c->chans[0]);
free(c); free(c);

157
sys/src/cmd/jpg/totif.c Normal file
View file

@ -0,0 +1,157 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <draw.h>
#include <memdraw.h>
#include "imagefile.h"
static Memimage *memtochan(Memimage *, ulong);
void
usage(void)
{
fprint(2, "usage: %s [-c 'comment'] "
"[-bBgGhHlLmprtT] [file]\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
Biobuf bout;
Memimage *i, *ni;
int fd, chanflag, comp, opt;
char *err, *file, *c;
ulong chan;
chan = BGR24;
chanflag = opt = 0;
comp = 1;
c = nil;
ARGBEGIN {
case 'b':
chan = GREY1;
chanflag = 1;
break;
case 'B':
chan = GREY2;
chanflag = 1;
break;
case 'c':
c = EARGF(usage());
break;
case 'g':
chan = GREY4;
chanflag = 1;
break;
case 'G':
chan = GREY8;
chanflag = 1;
break;
case 'h': /* huffman */
comp = 2;
break;
case 'H': /* t4 */
comp = 3;
opt = 0;
break;
case 'l': /* lzw */
comp = 5;
opt = 0;
break;
case 'L': /* lzw, horizontal differencing */
comp = 5;
opt = 1;
break;
case 'm': /* palette */
chan = CMAP8;
chanflag = 1;
break;
case 'p': /* packbits */
comp = 0x8005;
break;
case 'r': /* force BGR24 */
chan = BGR24;
chanflag = 1;
break;
case 't': /* t4 two-dimensional */
comp = 3;
opt = 1;
break;
case 'T': /* t6 */
comp = 4;
break;
default:
usage();
} ARGEND
if(argc > 1)
usage();
if(argc == 0) {
file = "<stdin>";
fd = 0;
} else {
file = argv[0];
if((fd = open(file, OREAD)) < 0)
sysfatal("open %s: %r", file);
}
if(Binit(&bout, 1, OWRITE) < 0)
sysfatal("Binit: %r");
memimageinit();
if((i = readmemimage(fd)) == nil)
sysfatal("readmemimage %s: %r", file);
close(fd);
if(comp >= 2 && comp <= 4) {
chan = GREY1;
chanflag = 1;
} else if(chan == GREY2) {
if((ni = memtochan(i, chan)) == nil)
sysfatal("memtochan: %r");
if(i != ni) {
freememimage(i);
i = ni;
}
chan = GREY4;
}
if(!chanflag) {
switch(i->chan) {
case GREY1:
case GREY4:
case GREY8:
case CMAP8:
case BGR24:
break;
case GREY2:
chan = GREY4;
chanflag = 1;
break;
default:
chanflag = 1;
break;
}
}
if(chanflag) {
if((ni = memtochan(i, chan)) == nil)
sysfatal("memtochan: %r");
if(i != ni) {
freememimage(i);
i = ni;
}
}
if((err = memwritetif(&bout, i, c, comp, opt)) != nil)
fprint(2, "%s: %s\n", argv0, err);
freememimage(i);
exits(err);
}
static Memimage *
memtochan(Memimage *i, ulong chan)
{
Memimage *ni;
if(i->chan == chan)
return i;
if((ni = allocmemimage(i->r, chan)) == nil)
return nil;
memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S);
return ni;
}

1341
sys/src/cmd/jpg/writetif.c Normal file

File diff suppressed because it is too large Load diff