1 /*
2  * in_pnm.cpp -- read a NetPBM PNM bitmap file
3  * by pts@fazekas.hu at Sat Mar  2 00:46:54 CET 2002
4  *
5  */
6 
7 #ifdef __GNUC__
8 #ifndef __clang__
9 #pragma implementation
10 #endif
11 #endif
12 
13 #include "image.hpp"
14 #include "error.hpp"
15 
16 #if USE_IN_PNM
17 
18 #include "gensio.hpp"
19 #include "input-pnm.ci"
20 #include <string.h>
21 
in_pnm_reader(Image::Loader::UFD * ufd,SimBuffer::Flat const &)22 static Image::Sampled *in_pnm_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) {
23   Image::Sampled *ret=0;
24   #if 0
25     FILE *f=((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false);
26     bitmap_type bitmap=pnm_load_image(f);
27   #else
28     Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
29     bitmap_type bitmap=pnm_load_image(ufdd);
30   #endif
31   /* Imp: Work without duplicated memory allocation */
32   if (BITMAP_PLANES(bitmap)==1) {
33     Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
34     memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
35     ret=img;
36   } else if (BITMAP_PLANES(bitmap)==3) {
37     Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
38     memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
39     /* fwrite(BITMAP_BITS(bitmap), 1, (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap), stdout); */
40     ret=img;
41   } else assert(0 && "invalid PNM depth");
42   delete [] BITMAP_BITS(bitmap);
43   if (ufdd->vi_getcc()=='P') {
44     ufdd->unread("P", 1);
45     // Error::sev(Error::NOTICE) << "PNM: loading alpha after PNM: "
46     //   " ftell=" << ftell(f) <<
47     //  " bytes=" << ((unsigned)bitmap.width*bitmap.height*bitmap.np)  << (Error*)0;
48     bitmap=pnm_load_image(ufdd);
49     // fwrite(bitmap.bitmap,1,(unsigned)bitmap.width*bitmap.height*bitmap.np,stdout);
50     /* Dat: black pixel is transparent */
51     if (BITMAP_PLANES(bitmap)!=1) Error::sev(Error::EERROR) << "PNM: alpha must be PBM or PGM" << (Error*)0;
52     if (BITMAP_WIDTH(bitmap)!=ret->getWd() || BITMAP_HEIGHT(bitmap)!=ret->getHt()) {
53       Error::sev(Error::EERROR) << "PNM: inconsistent width or height in alpha" << (Error*)0;
54     }
55     Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
56     memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
57     delete [] BITMAP_BITS(bitmap);
58     Image::Sampled *old=ret;
59     // old->packPal(); /* automatically called */
60     if ((ret=old->addAlpha(img))!=old) {
61       Error::sev(Error::NOTICE) << "PNM: loaded alpha after PNM" << (Error*)0;
62       delete old;
63     } else {
64       Error::sev(Error::NOTICE) << "PNM: loaded alpha, but no transparent pixels" << (Error*)0;
65     }
66     delete img;
67   }
68   /* fclose(f); */
69   return ret;
70 }
71 
in_pnm_checker(char buf[Image::Loader::MAGIC_LEN],char[Image::Loader::MAGIC_LEN],SimBuffer::Flat const &,Image::Loader::UFD *)72 static Image::Loader::reader_t in_pnm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
73   return (buf[0]=='P' && (buf[1]>='1' && buf[1]<='6') &&
74     (buf[2]=='\t' || buf[2]==' ' || buf[2]=='\r' || buf[2]=='\n' || buf[2]=='#'))
75    ? in_pnm_reader : 0;
76 }
77 
78 #else
79 #define in_pnm_checker NULLP
80 #endif /* USE_IN_PNM */
81 
82 Image::Loader in_pnm_loader = { "PNM", in_pnm_checker, 0 };
83