158 lines
2.5 KiB
C
158 lines
2.5 KiB
C
|
#include <u.h>
|
||
|
#include <libc.h>
|
||
|
#include <bio.h>
|
||
|
#include <draw.h>
|
||
|
#include <memdraw.h>
|
||
|
#include "imagefile.h"
|
||
|
|
||
|
static Memimage *memtochan(Memimage *, uint32_t);
|
||
|
|
||
|
void
|
||
|
usage(void)
|
||
|
{
|
||
|
fprint(2, "usage: %s [-c 'comment'] "
|
||
|
"[-3bgGhklLptvyY] [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;
|
||
|
uint32_t chan;
|
||
|
|
||
|
chan = BGR24;
|
||
|
chanflag = opt = 0;
|
||
|
comp = 1;
|
||
|
c = nil;
|
||
|
ARGBEGIN {
|
||
|
case '3': /* force RGB */
|
||
|
chan = BGR24;
|
||
|
chanflag = 1;
|
||
|
break;
|
||
|
case 'b':
|
||
|
chan = GREY1;
|
||
|
chanflag = 1;
|
||
|
break;
|
||
|
case 'c':
|
||
|
c = EARGF(usage());
|
||
|
break;
|
||
|
case 'g': /* t4 */
|
||
|
comp = 3;
|
||
|
opt = 0;
|
||
|
break;
|
||
|
case 'G': /* t4 two-dimensional */
|
||
|
comp = 3;
|
||
|
opt = 1;
|
||
|
break;
|
||
|
case 'h': /* huffman */
|
||
|
comp = 2;
|
||
|
break;
|
||
|
case 'k':
|
||
|
chan = GREY8;
|
||
|
chanflag = 1;
|
||
|
break;
|
||
|
case 'l': /* lzw */
|
||
|
comp = 5;
|
||
|
opt = 0;
|
||
|
break;
|
||
|
case 'L': /* lzw, horizontal differencing */
|
||
|
comp = 5;
|
||
|
opt = 1;
|
||
|
break;
|
||
|
case 'p': /* packbits */
|
||
|
comp = 0x8005;
|
||
|
break;
|
||
|
case 't': /* t6 */
|
||
|
comp = 4;
|
||
|
break;
|
||
|
case 'v': /* RGBV */
|
||
|
chan = CMAP8;
|
||
|
chanflag = 1;
|
||
|
break;
|
||
|
case 'y':
|
||
|
chan = GREY2;
|
||
|
chanflag = 1;
|
||
|
break;
|
||
|
case 'Y':
|
||
|
chan = GREY4;
|
||
|
chanflag = 1;
|
||
|
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, uint32_t 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;
|
||
|
}
|