w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

in_jai.cpp
Go to the documentation of this file.
1 /*
2  * in_jai.cpp -- read a JPEG file as-is
3  * by pts@math.bme.hu at Sun Mar 17 20:15:25 CET 2002
4  */
5 /* Imp: test this code with various JPEG files! */
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_JAI
17 
18 #include "in_jai.hpp"
19 #include <string.h> /* memchr() */
20 #include <stdio.h>
21 
22 /* --- */
23 
24 class JAI: public Image::Sampled {
25  public:
26  /** (Horiz<<4+Vert) sampling factor for the first color component. Usually
27  * 0x11, but TIFF defaults to 0x22.
28  */
29  JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_);
30  virtual void copyRGBRow(char *to, dimen_t whichrow) const;
31  virtual void to8();
32  virtual Image::Indexed* toIndexed();
33  virtual bool canGray() const;
34  // virtual void setBpc(unsigned char bpc_);
35  virtual Image::RGB * toRGB(unsigned char bpc_);
36  virtual Image::Gray * toGray(unsigned char bpc_);
37  virtual unsigned char minRGBBpc() const;
38  virtual Image::Sampled* addAlpha(Image::Gray *al);
39  void fixEOI();
40 };
41 
42 JAI::JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_) {
43  param_assert(cs_<=5);
44  // init(0,0,wd_,ht_,bpc_,TY_BLACKBOX,cs2cpp[cs_]);
45  cs=cs_;
46  bpc=8; (void)bpc_; // bpc=bpc_; /* /DCTDecode supports only BitsPerComponent==8 */
48  wd=wd_;
49  ht=ht_;
50  cpp=cs2cpp[cs_];
51  // pred=1;
52  transpc=0x1000000UL; /* Dat: this means: no transparent color */
53  rlen=0;
54  beg=new char[len=0+flen_+0+bpc];
55  rowbeg=(headp=const_cast<char*>(beg))+flen_;
56  xoffs=SOF_offs_;
57  trail=const_cast<char*>(beg)+len-bpc;
58  const_cast<char*>(beg)[len-1]=hvs_; /* dirty place */
59 }
60 
61 void JAI::fixEOI() {
62  /* by pts@fazekas.hu at Tue Jun 4 15:36:12 CEST 2002 */
63  if (rowbeg[-2]!='\xFF' || rowbeg[-1]!='\xD9') {
64  *rowbeg++='\xFF';
65  *rowbeg++='\xD9';
66  }
67 }
68 
70  Error::sev(Error::WARNING) << "JAI: alpha channel ignored" << (Error*)0;
71  return this;
72 }
73 
74 
75 unsigned char JAI:: minRGBBpc() const { return bpc; }
76 void JAI::copyRGBRow(char*, dimen_t) const { assert(0); }
77 void JAI::to8() { assert(0); }
79 bool JAI::canGray() const { return cs==CS_GRAYSCALE; }
80 Image::RGB * JAI::toRGB(unsigned char) { assert(0); return 0; }
81 Image::Gray * JAI::toGray(unsigned char) { assert(0); return 0; }
82 
83 /* --- The following code is based on standard/image.c from PHP4 */
84 
85 /* some defines for the different JPEG block types */
86 #define M_SOF0 0xC0 /* Start Of Frame0: Baseline JPEG */
87 #define M_SOF1 0xC1 /* N indicates which compression process */
88 #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
89 #define M_SOF3 0xC3
90 #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
91 #define M_SOF6 0xC6
92 #define M_SOF7 0xC7
93 #define M_SOF9 0xC9
94 #define M_SOF10 0xCA
95 #define M_SOF11 0xCB
96 #define M_SOF13 0xCD
97 #define M_SOF14 0xCE
98 #define M_SOF15 0xCF
99 #define M_SOI 0xD8
100 #define M_EOI 0xD9 /* End Of Image (end of datastream) */
101 #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
102 #define M_APP0 0xe0
103 #define M_APP1 0xe1
104 #define M_APP2 0xe2
105 #define M_APP3 0xe3
106 #define M_APP4 0xe4
107 #define M_APP5 0xe5
108 #define M_APP6 0xe6
109 #define M_APP7 0xe7
110 #define M_APP8 0xe8
111 #define M_APP9 0xe9
112 #define M_APP10 0xea
113 #define M_APP11 0xeb
114 #define M_APP12 0xec
115 #define M_APP13 0xed
116 #define M_APP14 0xee
117 #define M_APP15 0xef
118 
119 
120 #if 0
121 static unsigned int jai_next_marker(FILE *fp)
122  /* get next marker byte from file */
123 {
124  int c;
125 
126 #if 0 /**** pts ****/
127  /* skip unimportant stuff */
128  c = MACRO_GETC(fp);
129  while (c != 0xff) {
130  if ((c = MACRO_GETC(fp)) == EOF)
131  return M_EOI; /* we hit EOF */
132  }
133 #else
134  if (0xff!=(c=MACRO_GETC(fp))) return M_EOI;
135 #endif
136 
137 
138  /* get marker byte, swallowing possible padding */
139  do {
140  if ((c = MACRO_GETC(fp)) == EOF)
141  return M_EOI; /* we hit EOF */
142  } while (c == 0xff);
143 
144  return (unsigned int) c;
145 }
146 #endif
147 
148 #if 0
149 static inline int getc_(FILE *f) { return MACRO_GETC(f); }
150 static inline long ftell_(FILE *f) { return ftell(f); }
151 template <class T>
152 static unsigned short jai_read2(T *fp);
153 template <class T>
154 static void jai_handle_jpeg(struct jai_gfxinfo *result, T *fp) {
155 #endif
156 /* Dat: removed templates at Tue Mar 11 19:59:16 CET 2003, because decoding
157  * JPEG headers isn't time-critical
158  */
159 
160 static inline unsigned short jai_read2(GenBuffer::Readable *fp) {
161 #if 0
162  unsigned char a[ 2 ];
163  /* just return 0 if we hit the end-of-file */
164  if (fread(a,sizeof(a),1,fp) != 1) return 0;
165  return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]);
166 #else
167  int a=fp->vi_getcc(), b=fp->vi_getcc();
168  /* just return 0 if we hit the end-of-file */
169  return a>=0 && b>=0 ? (a<<8)+b : 0;
170 #endif
171 }
172 
173 /** main loop to parse JPEG structure */
174 void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline) {
175  int c;
176  unsigned int length;
177  unsigned char had_adobe;
178 
179  result->bad=9; /* signal invalid return value */
180  result->id_rgb=0;
181  result->had_jfif=0;
182  result->colortransform=127; /* no Adobe marker yet */
183  // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */
184 
185  /* Verify JPEG header */
186  /* Dat: maybe 0xFF != '\xFF' */
187  if ((c=fp->vi_getcc())!=0xFF) return;
188  while ((c=fp->vi_getcc())==0xFF) ;
189  if (c!=M_SOI) return;
190 
191  result->bad=1;
192  // fprintf(stderr, "welcome ofs=%ld\n", fp->vi_tell());
193  while (1) {
194  if ((c=fp->vi_getcc())!=0xFF) { result->bad=8; return; }
195  while ((c=fp->vi_getcc())==0xFF) ;
196  if (c==-1) { result->bad=2; return; }
197  switch (c) {
198  case M_SOF0: do_SOF:
199  if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */
200  result->SOF_type=c-M_SOF0;
201  result->SOF_offs=fp->vi_tell();
202  // fprintf(stderr, "SOF_offs=%d\n", result->SOF_offs);
203  /* handle SOFn block */
205  result->bpc = fp->vi_getcc();
206  result->height = jai_read2(fp);
207  result->width = jai_read2(fp);
208  result->cpp = fp->vi_getcc();
209  if ((length-=8)!=3U*result->cpp) return;
210  if (result->bpc!=8) { result->bad=6; return; }
211  if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) { result->bad=5; return; }
212  assert(length>=3);
213  if (result->cpp==3) {
214  result->id_rgb =fp->vi_getcc()=='R'; result->hvs=fp->vi_getcc(); fp->vi_getcc();
215  result->id_rgb&=fp->vi_getcc()=='G'; fp->vi_getcc(); fp->vi_getcc();
216  result->id_rgb&=fp->vi_getcc()=='B'; fp->vi_getcc(); fp->vi_getcc();
217  } else { length-=2; fp->vi_getcc(); result->hvs=fp->vi_getcc(); while (length--!=0) fp->vi_getcc(); }
218  result->bad=2;
219  break;
220  case M_SOF1:
221  case M_SOF2:
222  case M_SOF3:
223  case M_SOF5:
224  case M_SOF6:
225  case M_SOF7:
226  case M_SOF9:
227  case M_SOF10:
228  case M_SOF11:
229  case M_SOF13:
230  case M_SOF14:
231  case M_SOF15:
232  if (!must_be_baseline) goto do_SOF;
233  // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0);
234  result->bad=3;
235  return;
236  case M_SOS: /* we are about to hit image data. We're done. Success. */
237  if (result->bad==2 /* && !feof(fp)*/) { /* Dat: !feof() already guaranteed */
238  if (result->cpp==1) {
240  } else if (result->cpp==3) {
241  result->colorspace=Image::Sampled::CS_YCbCr;
242  if (result->had_jfif!=0) ;
243  else if (result->colortransform==0) result->colorspace=Image::Sampled::CS_RGB;
244  else if (result->colortransform==1) ;
245  else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0;
246  else if (result->id_rgb!=0) result->colorspace=Image::Sampled::CS_RGB;
247  /* Imp: check for id_ycbcr */
248  else Error::sev(Error::WARNING) << "JAI: assuming YCbCr color space" << (Error*)0;
249  } else if (result->cpp==4) {
250  result->colorspace=Image::Sampled::CS_CMYK;
251  if (result->colortransform==0) ;
252  else if (result->colortransform==2) result->colorspace=Image::Sampled::CS_YCCK;
253  else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0;
254  } else assert(0);
255  result->bad=0;
256  }
257  /* fall through */
258  case M_EOI: /* premature EOF */
259  return;
260  case M_APP0: /* JFIF application-specific marker */
262  if (length==2+4+1+2+1+2+2+1+1) {
263  result->had_jfif=fp->vi_getcc()=='J' && fp->vi_getcc()=='F' && fp->vi_getcc()=='I' &&
264  fp->vi_getcc()=='F' && fp->vi_getcc()==0;
265  length-=7;
266  } else length-=2;
267  while (length--!=0) fp->vi_getcc();
268  break;
269  case M_APP14: /* Adobe application-specific marker */
271  if ((length-=2)==5+2+2+2+1) {
272  had_adobe=fp->vi_getcc()=='A' && fp->vi_getcc()=='d' && fp->vi_getcc()=='o' &&
273  fp->vi_getcc()=='b' && fp->vi_getcc()=='e' && ((unsigned char)fp->vi_getcc())>=1;
274  fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc();
275  if (had_adobe) result->colortransform=fp->vi_getcc();
276  else fp->vi_getcc();
277  } else while (length--!=0) fp->vi_getcc();
278  break;
279  case M_APP1:
280  case M_APP2:
281  case M_APP3:
282  case M_APP4:
283  case M_APP5:
284  case M_APP6:
285  case M_APP7:
286  case M_APP8:
287  case M_APP9:
288  case M_APP10:
289  case M_APP11:
290  case M_APP12:
291  case M_APP13:
292  case M_APP15:
293  /* fall through */
294  default: { /* anything else isn't interesting */
295  /* skip over a variable-length block; assumes proper length marker */
296  unsigned short length;
297  length = jai_read2(fp);
298  length -= 2; /* length includes itself */
299  #if 0 /**** pts: fseek would disturb later ftell()s and feof()s */
300  fseek(fp, (long) length, SEEK_CUR); /* skip the header */
301  #else
302  while (length--!=0) fp->vi_getcc(); /* make feof(fp) correct */
303  #endif
304  }
305  }
306  }
307 }
308 
309 char const*jai_errors[]={
310  (char const*)NULLP,
311  /*1*/ "missing SOF0 marker",
312  /*2*/ "premature EOF",
313  /*3*/ "not a Baseline JPEG (SOF must be SOF0)",
314  /*4*/ "more SOF0 markers",
315  /*5*/ "bad # components",
316  /*6*/ "bad bpc",
317  /*7*/ "?",
318  /*8*/ "0xFF expected",
319  /*9*/ "invalid JPEG header",
320  // /*10*/ "not ending with EOI", /* not output by jai_handle_jpeg! */
321 };
322 
323 static Image::Sampled *in_jai_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) {
324  // assert(0);
325  struct jai_gfxinfo gi;
327  FILE *file_=ufdd->getFILE(/*seekable:*/true);
328  jai_parse_jpeg(&gi, ufdd);
329  // jai_parse_jpeg(&gi, (FILE*)file_);
330  // long ftel=ftell((FILE*)file_);
331  if (gi.bad!=0) Error::sev(Error::EERROR) << "JAI: " << jai_errors[gi.bad] << (Error*)0;
332  // printf("ftell=%lu\n", ftell((FILE*)file_));
333  fseek((FILE*)file_, 0L, 2); /* EOF */
334  long flen=ftell((FILE*)file_); /* skip extra bytes after EOI. Imp: no need to do this */
335  // fprintf(stderr, "flen=%lu\n", flen);
336  assert(flen>2);
337  rewind((FILE*)file_);
338  JAI *ret=new JAI(gi.width,gi.height,gi.bpc,gi.colorspace,flen,gi.SOF_offs,gi.hvs);
339  if (fread(ret->getHeadp(), flen, 1, (FILE*)file_)!=1 || ferror((FILE*)file_)) {
340  ret->fixEOI();
341  /* fclose((FILE*)file_); */
342  Error::sev(Error::EERROR) << "JAI: IO error" << (Error*)0;
343  }
344  /* fclose((FILE*)file_); */
345  return ret;
346 }
347 
349  if (0!=memcmp(buf, "\xff\xd8\xff", 3)
350  || !(loadHints.findFirst((char const*)",jpeg-asis,",6)!=loadHints.getLength() || loadHints.findFirst((char const*)",asis,",6)!=loadHints.getLength())
351  ) return 0;
353  ufdd->seek(0);
355  ufdd->seek(0);
356  return ret;
357 }
358 
359 #if 0 /* Filter::FlatR* used by JPEGSOF0Encode::vi_write() in appliers.cpp */
360 static inline int getc_(Filter::FlatR *f) { return f->getcc(); }
361 static inline long ftell_(Filter::FlatR *f) { return f->tell(); }
362 void jai_parse_jpeg(struct jai_gfxinfo *result, Filter::FlatR *f) {
364 }
365 void jai_parse_jpeg(struct jai_gfxinfo *result, FILE *f) {
367 }
368 #endif
369 
370 #if 0 /* unused */
371 int jai_is_baseline_jpeg(char const* filename) {
372  /* by pts@fazekas.hu at Tue Mar 11 20:27:56 CET 2003 */
373  FILE *f=fopen(filename, "rb");
374  if (!f) return -1;
375  Filter::FILED filed(f, /*closep:*/true);
376  return jai_is_baseline_jpeg(&filed);
377 }
378 #endif
380  char buf[3];
381  struct jai_gfxinfo gi;
382  bool qfalse=(3!=fp->vi_read(buf, 3) || 0!=memcmp(buf, "\xff\xd8\xff", 3));
383  fp->unread(buf, 3);
384  if (qfalse) return false;
385  fp->getFILE(/*seekable*/true); /* make it seekable, so the caller can seek back */
386  jai_parse_jpeg(&gi, fp, /*must_be_baseline:*/false);
387  fp->seek(0);
388  return gi.bad!=0 ? -1 : gi.SOF_type==0;
389 }
390 #else
391 #define in_jai_checker (Image::Loader::checker_t)NULLP
392 #endif /* USE_IN_JAI */
393 
Definition: error.hpp:20
static GenBuffer::Writable & sev(level_t level)
Definition: error.cpp:58
@ EERROR
Definition: error.hpp:29
@ WARNING
Definition: error.hpp:31
void seek(long abs_ofs)
Definition: gensio.cpp:397
unsigned char ty
Definition: image.hpp:91
char * rowbeg
Definition: image.hpp:66
rlen_t rlen
Definition: image.hpp:75
char * headp
Definition: image.hpp:65
unsigned int dimen_t
Definition: image.hpp:40
char * trail
Definition: image.hpp:67
dimen_t ht
Definition: image.hpp:77
slen_t xoffs
Definition: image.hpp:69
rgb_t transpc
Definition: image.hpp:89
static const unsigned char cs2cpp[6]
Definition: image.hpp:61
unsigned char cpp
Definition: image.hpp:85
unsigned char bpc
Definition: image.hpp:87
dimen_t wd
Definition: image.hpp:79
Definition: in_jai.cpp:24
virtual void to8()
Definition: in_jai.cpp:77
virtual bool canGray() const
Definition: in_jai.cpp:79
void fixEOI()
Definition: in_jai.cpp:61
virtual Image::RGB * toRGB(unsigned char bpc_)
Definition: in_jai.cpp:80
JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_)
Definition: in_jai.cpp:42
virtual unsigned char minRGBBpc() const
Definition: in_jai.cpp:75
virtual void copyRGBRow(char *to, dimen_t whichrow) const
Definition: in_jai.cpp:76
virtual Image::Indexed * toIndexed()
Definition: in_jai.cpp:78
virtual Image::Gray * toGray(unsigned char bpc_)
Definition: in_jai.cpp:81
virtual Image::Sampled * addAlpha(Image::Gray *al)
Definition: in_jai.cpp:69
const char * beg
Definition: gensi.hpp:250
slen_t len
Definition: gensi.hpp:251
virtual slen_t getLength() const
Definition: gensi.hpp:253
slen_t findFirst(char const c) const
Definition: gensi.cpp:356
unsigned int slen_t
Definition: config2.h:37
#define NULLP
Definition: config2.h:66
#define MACRO_GETC
Definition: config2.h:333
#define param_assert
Definition: config2.h:96
#define b
Definition: jpegint.h:372
#define fopen
Definition: xxstdio.h:21
#define fread
Definition: xxstdio.h:25
#define fseek
Definition: xxstdio.h:30
#define ftell
Definition: xxstdio.h:31
#define T
Definition: fmt.h:20
static void
Definition: fpif.c:118
integer ftell_(integer *Unit)
Definition: ftell_.c:23
mpz_t * f
Definition: gen-fib.c:34
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define memcmp(s1, s2, n)
Definition: gsftopk.c:66
#define M_APP2
Definition: in_jai.cpp:104
#define M_APP11
Definition: in_jai.cpp:113
static Image::Loader::reader_t in_jai_checker(char buf[Image::Loader::MAGIC_LEN], char[Image::Loader::MAGIC_LEN], SimBuffer::Flat const &loadHints, Image::Loader::UFD *ufd)
Definition: in_jai.cpp:348
#define M_APP9
Definition: in_jai.cpp:111
#define M_SOF7
Definition: in_jai.cpp:92
#define M_APP1
Definition: in_jai.cpp:103
#define M_SOF6
Definition: in_jai.cpp:91
#define M_APP5
Definition: in_jai.cpp:107
#define M_EOI
Definition: in_jai.cpp:100
int jai_is_baseline_jpeg(Filter::UngetFILED *fp)
Definition: in_jai.cpp:379
#define M_SOF11
Definition: in_jai.cpp:95
#define M_SOF9
Definition: in_jai.cpp:93
#define M_SOF15
Definition: in_jai.cpp:98
#define M_APP8
Definition: in_jai.cpp:110
static Image::Sampled * in_jai_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const &)
Definition: in_jai.cpp:323
#define M_SOF3
Definition: in_jai.cpp:89
#define M_APP13
Definition: in_jai.cpp:115
#define M_APP15
Definition: in_jai.cpp:117
#define M_APP4
Definition: in_jai.cpp:106
#define M_SOF13
Definition: in_jai.cpp:96
#define M_APP12
Definition: in_jai.cpp:114
#define M_APP3
Definition: in_jai.cpp:105
char const * jai_errors[]
Definition: in_jai.cpp:309
Image::Loader in_jai_loader
Definition: in_jai.cpp:394
static unsigned short jai_read2(GenBuffer::Readable *fp)
Definition: in_jai.cpp:160
#define M_SOF10
Definition: in_jai.cpp:94
#define M_APP6
Definition: in_jai.cpp:108
void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline)
Definition: in_jai.cpp:174
#define M_SOF1
Definition: in_jai.cpp:87
#define M_APP7
Definition: in_jai.cpp:109
#define M_SOI
Definition: in_jai.cpp:99
#define M_SOF5
Definition: in_jai.cpp:90
#define M_APP0
Definition: in_jai.cpp:102
#define M_APP14
Definition: in_jai.cpp:116
#define M_SOF14
Definition: in_jai.cpp:97
#define M_SOF0
Definition: in_jai.cpp:86
#define M_APP10
Definition: in_jai.cpp:112
#define M_SOF2
Definition: in_jai.cpp:88
#define M_SOS
Definition: in_jai.cpp:101
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
static unsigned int jai_next_marker(FILE *fp)
static void jai_handle_jpeg(struct gfxinfo *result, FILE *fp)
#define SEEK_CUR
Definition: ftzconf.h:250
#define EOF
Definition: afmparse.c:59
#define buf
static int ret
Definition: convert.c:72
#define length(c)
Definition: ctangleboot.c:65
char * filename[256]
Definition: pbmtopk.c:46
#define fp
real to[600]
Definition: pmxab.c:87
static Filter::UngetFILED * ufd
Definition: sam2p_main.cpp:269
Sampled *(* reader_t)(UFD *ufd, SimBuffer::Flat const &loadHints)
Definition: image.hpp:276
Definition: pst1form.c:310
unsigned char bad
Definition: in_jai.hpp:23
slen_t SOF_offs
Definition: in_jai.hpp:32
unsigned char bpc
Definition: in_jai.hpp:23
unsigned char SOF_type
Definition: in_jai.hpp:21
unsigned char hvs
Definition: in_jai.hpp:27
slen_t width
Definition: in_jai.hpp:28
unsigned char colorspace
Definition: in_jai.hpp:22
slen_t height
Definition: in_jai.hpp:28
#define FILE
Definition: t1stdio.h:34
#define ferror(f)
Definition: t1stdio.h:110
@ L
Definition: ubidiimp.h:45