Why not?
This commit is contained in:
parent
a01e58366c
commit
28994509cc
82 changed files with 13293 additions and 0 deletions
238
src/cmd/jpg/readppm.c
Normal file
238
src/cmd/jpg/readppm.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <draw.h>
|
||||
#include <ctype.h>
|
||||
#include "imagefile.h"
|
||||
|
||||
Rawimage *readppm(Biobuf*, Rawimage*);
|
||||
|
||||
/*
|
||||
* fetch a non-comment character.
|
||||
*/
|
||||
static
|
||||
int
|
||||
Bgetch(Biobuf *b)
|
||||
{
|
||||
int c;
|
||||
|
||||
for(;;) {
|
||||
c = Bgetc(b);
|
||||
if(c == '#') {
|
||||
while((c = Bgetc(b)) != Beof && c != '\n')
|
||||
;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fetch a nonnegative decimal integer.
|
||||
*/
|
||||
static
|
||||
int
|
||||
Bgetint(Biobuf *b)
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
|
||||
while((c = Bgetch(b)) != Beof && !isdigit(c))
|
||||
;
|
||||
if(c == Beof)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
i = i*10 + (c-'0');
|
||||
} while((c = Bgetch(b)) != Beof && isdigit(c));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
Bgetdecimalbit(Biobuf *b)
|
||||
{
|
||||
int c;
|
||||
while((c = Bgetch(b)) != Beof && c != '0' && c != '1')
|
||||
;
|
||||
if(c == Beof)
|
||||
return -1;
|
||||
return c == '1';
|
||||
}
|
||||
|
||||
static int bitc, nbit;
|
||||
|
||||
static
|
||||
int
|
||||
Bgetbit(Biobuf *b)
|
||||
{
|
||||
if(nbit == 0) {
|
||||
nbit = 8;
|
||||
bitc = Bgetc(b);
|
||||
if(bitc == -1)
|
||||
return -1;
|
||||
}
|
||||
nbit--;
|
||||
return (bitc >> (nbit-1)) & 0x1;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
Bflushbit(Biobuf *b)
|
||||
{
|
||||
USED(b);
|
||||
nbit = 0;
|
||||
}
|
||||
|
||||
|
||||
Rawimage**
|
||||
readpixmap(int fd, int colorspace)
|
||||
{
|
||||
Rawimage **array, *a;
|
||||
Biobuf b;
|
||||
char buf[ERRMAX];
|
||||
int i;
|
||||
char *e;
|
||||
|
||||
USED(colorspace);
|
||||
if(Binit(&b, fd, OREAD) < 0)
|
||||
return nil;
|
||||
|
||||
werrstr("");
|
||||
e = "out of memory";
|
||||
if((array = malloc(sizeof *array)) == nil)
|
||||
goto Error;
|
||||
if((array[0] = malloc(sizeof *array[0])) == nil)
|
||||
goto Error;
|
||||
memset(array[0], 0, sizeof *array[0]);
|
||||
|
||||
for(i=0; i<3; i++)
|
||||
array[0]->chans[i] = nil;
|
||||
|
||||
e = "bad file format";
|
||||
switch(Bgetc(&b)) {
|
||||
case 'P':
|
||||
Bungetc(&b);
|
||||
a = readppm(&b, array[0]);
|
||||
break;
|
||||
default:
|
||||
a = nil;
|
||||
break;
|
||||
}
|
||||
if(a == nil)
|
||||
goto Error;
|
||||
array[0] = a;
|
||||
|
||||
return array;
|
||||
|
||||
Error:
|
||||
if(array)
|
||||
free(array[0]);
|
||||
free(array);
|
||||
|
||||
errstr(buf, sizeof buf);
|
||||
if(buf[0] == 0)
|
||||
strcpy(buf, e);
|
||||
errstr(buf, sizeof buf);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
typedef struct Pix Pix;
|
||||
struct Pix {
|
||||
char magic;
|
||||
int maxcol;
|
||||
int (*fetch)(Biobuf*);
|
||||
int nchan;
|
||||
int chandesc;
|
||||
int invert;
|
||||
void (*flush)(Biobuf*);
|
||||
};
|
||||
|
||||
static Pix pix[] = {
|
||||
{ '1', 1, Bgetdecimalbit, 1, CY, 1, nil }, /* portable bitmap */
|
||||
{ '4', 1, Bgetbit, 1, CY, 1, Bflushbit }, /* raw portable bitmap */
|
||||
{ '2', 0, Bgetint, 1, CY, 0, nil }, /* portable greymap */
|
||||
{ '5', 0, Bgetc, 1, CY, 0, nil }, /* raw portable greymap */
|
||||
{ '3', 0, Bgetint, 3, CRGB, 0, nil }, /* portable pixmap */
|
||||
{ '6', 0, Bgetc, 3, CRGB, 0, nil }, /* raw portable pixmap */
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
Rawimage*
|
||||
readppm(Biobuf *b, Rawimage *a)
|
||||
{
|
||||
int i, ch, wid, ht, r, c;
|
||||
int maxcol, nchan, invert;
|
||||
int (*fetch)(Biobuf*);
|
||||
uchar *rgb[3];
|
||||
char buf[ERRMAX];
|
||||
char *e;
|
||||
Pix *p;
|
||||
|
||||
e = "bad file format";
|
||||
if(Bgetc(b) != 'P')
|
||||
goto Error;
|
||||
|
||||
c = Bgetc(b);
|
||||
for(p=pix; p->magic; p++)
|
||||
if(p->magic == c)
|
||||
break;
|
||||
if(p->magic == 0)
|
||||
goto Error;
|
||||
|
||||
|
||||
wid = Bgetint(b);
|
||||
ht = Bgetint(b);
|
||||
if(wid <= 0 || ht <= 0)
|
||||
goto Error;
|
||||
a->r = Rect(0,0,wid,ht);
|
||||
|
||||
maxcol = p->maxcol;
|
||||
if(maxcol == 0) {
|
||||
maxcol = Bgetint(b);
|
||||
if(maxcol <= 0)
|
||||
goto Error;
|
||||
}
|
||||
|
||||
e = "out of memory";
|
||||
for(i=0; i<p->nchan; i++)
|
||||
if((rgb[i] = a->chans[i] = malloc(wid*ht)) == nil)
|
||||
goto Error;
|
||||
a->nchans = p->nchan;
|
||||
a->chanlen = wid*ht;
|
||||
a->chandesc = p->chandesc;
|
||||
|
||||
e = "error reading file";
|
||||
|
||||
fetch = p->fetch;
|
||||
nchan = p->nchan;
|
||||
invert = p->invert;
|
||||
for(r=0; r<ht; r++) {
|
||||
for(c=0; c<wid; c++) {
|
||||
for(i=0; i<nchan; i++) {
|
||||
if((ch = (*fetch)(b)) < 0)
|
||||
goto Error;
|
||||
if(invert)
|
||||
ch = maxcol - ch;
|
||||
*rgb[i]++ = (ch * 255)/maxcol;
|
||||
}
|
||||
}
|
||||
if(p->flush)
|
||||
(*p->flush)(b);
|
||||
}
|
||||
|
||||
return a;
|
||||
|
||||
Error:
|
||||
errstr(buf, sizeof buf);
|
||||
if(buf[0] == 0)
|
||||
strcpy(buf, e);
|
||||
errstr(buf, sizeof buf);
|
||||
|
||||
for(i=0; i<3; i++)
|
||||
free(a->chans[i]);
|
||||
free(a->cmap);
|
||||
return nil;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue