• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

DjVuImage.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: DjVuImage.cpp,v 1.10 2005/04/27 16:34:13 leonb Exp $
00055 // $Name: release_3_5_15 $
00056 
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063 
00064 #include "DjVuImage.h"
00065 #include "GScaler.h"
00066 #include "DjVuDocument.h"
00067 #include "DjVuPalette.h"
00068 #include "GContainer.h"
00069 #include "GSmartPointer.h"
00070 #include "JB2Image.h"
00071 #include "IW44Image.h"
00072 #include "DataPool.h"
00073 #include "ByteStream.h"
00074 #include "GMapAreas.h"
00075 #include "DjVuText.h"
00076 #include "IFFByteStream.h"
00077 #include "BSByteStream.h"
00078 #include "debug.h"
00079 #include <stdarg.h>
00080 
00081 
00082 #ifdef HAVE_NAMESPACES
00083 namespace DJVU {
00084 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00085 }
00086 #endif
00087 #endif
00088 
00089 
00090 
00092 
00093 DjVuImage::DjVuImage(void) 
00094 : rotate_count(-1),relayout_sent(false)
00095 {
00096 }
00097 
00098 void
00099 DjVuImage::connect(const GP<DjVuFile> & xfile)
00100 {
00101    file=xfile;
00102    DjVuPort::get_portcaster()->add_route(file, this);
00103 }
00104 
00105 
00106 
00107 
00109 
00110 GP<DjVuInfo>
00111 DjVuImage::get_info(const GP<DjVuFile> & file) const
00112 {
00113    if (file->info)
00114    {
00115      if(rotate_count<0)
00116      {
00117        const_cast<DjVuImage *>(this)->init_rotate(*(file->info));
00118      }
00119      return file->info;
00120    }
00121    GPList<DjVuFile> list=file->get_included_files();
00122    for(GPosition pos=list;pos;++pos)
00123    {
00124       GP<DjVuInfo> info=get_info(list[pos]);
00125       if (info) 
00126       {
00127         if(rotate_count<0)
00128         {
00129           const_cast<DjVuImage *>(this)->init_rotate(*(file->info));
00130         }
00131         return info;
00132       }
00133    }
00134    return 0;
00135 }
00136 
00137 GP<IW44Image>
00138 DjVuImage::get_bg44(const GP<DjVuFile> & file) const
00139 {
00140    if (file->bg44)
00141      return file->bg44;
00142    GPList<DjVuFile> list=file->get_included_files();
00143    for(GPosition pos=list;pos;++pos)
00144    {
00145       GP<IW44Image> bg44=get_bg44(list[pos]);
00146       if (bg44)
00147         return bg44;
00148    }
00149    return 0;
00150 }
00151 
00152 GP<GPixmap>
00153 DjVuImage::get_bgpm(const GP<DjVuFile> & file) const
00154 {
00155    if (file->bgpm)
00156      return file->bgpm;
00157    GPList<DjVuFile> list=file->get_included_files();
00158    for(GPosition pos=list;pos;++pos)
00159    {
00160       GP<GPixmap> bgpm=get_bgpm(list[pos]);
00161       if (bgpm) return bgpm;
00162    }
00163    return 0;
00164 }
00165 
00166 GP<JB2Image>
00167 DjVuImage::get_fgjb(const GP<DjVuFile> & file) const
00168 {
00169    if (file->fgjb)
00170      return file->fgjb;
00171    GPList<DjVuFile> list=file->get_included_files();
00172    for(GPosition pos=list;pos;++pos)
00173    {
00174       GP<JB2Image> fgjb=get_fgjb(list[pos]);
00175       if (fgjb)
00176         return fgjb;
00177    }
00178    return 0;
00179 }
00180 
00181 GP<GPixmap>
00182 DjVuImage::get_fgpm(const GP<DjVuFile> & file) const
00183 {
00184    if (file->fgpm)
00185      return file->fgpm;
00186    GPList<DjVuFile> list=file->get_included_files();
00187    for(GPosition pos=list;pos;++pos)
00188    {
00189       GP<GPixmap> fgpm=get_fgpm(list[pos]);
00190       if (fgpm)
00191         return fgpm;
00192    }
00193    return 0;
00194 }
00195 
00196 GP<DjVuPalette>
00197 DjVuImage::get_fgbc(const GP<DjVuFile> & file) const
00198 {
00199    if (file->fgbc)
00200      return file->fgbc;
00201    GPList<DjVuFile> list=file->get_included_files();
00202    for(GPosition pos=list;pos;++pos)
00203    {
00204       GP<DjVuPalette> fgbc=get_fgbc(list[pos]);
00205       if (fgbc) return fgbc;
00206    }
00207    return 0;
00208 }
00209 
00210 GP<DjVuInfo>   
00211 DjVuImage::get_info() const
00212 {
00213    if (file)
00214    {
00215      return get_info(file);
00216    }else
00217    {
00218      return 0;
00219    }
00220 }
00221 
00222 GP<ByteStream>
00223 DjVuImage::get_anno() const
00224 {
00225    GP<ByteStream> out = ByteStream::create();
00226    ByteStream &mbs = *out;
00227    if (file) 
00228    {
00229      file->merge_anno(mbs);
00230    }
00231    mbs.seek(0);
00232    if(!mbs.size())
00233    {
00234      out=0;
00235    }
00236    return out;
00237 }
00238 
00239 GP<ByteStream>
00240 DjVuImage::get_text() const
00241 {
00242    GP<ByteStream> out = ByteStream::create();
00243    ByteStream &mbs = *out;
00244    if (file) 
00245    {
00246      file->get_text(mbs);
00247    }
00248    mbs.seek(0);
00249    if(!mbs.size())
00250    {
00251      out=0;
00252    }
00253    return out;
00254 }
00255 
00256 GP<ByteStream>
00257 DjVuImage::get_meta() const
00258 {
00259    GP<ByteStream> out = ByteStream::create();
00260    ByteStream &mbs = *out;
00261    if (file) 
00262    {
00263      file->get_meta(mbs);
00264    }
00265    mbs.seek(0);
00266    if(!mbs.size())
00267    {
00268      out=0;
00269    }
00270    return out;
00271 }
00272 
00273 GP<IW44Image>   
00274 DjVuImage::get_bg44() const
00275 {
00276    if (file)
00277      return get_bg44(file);
00278    else
00279      return 0;
00280 }
00281 
00282 GP<GPixmap>   
00283 DjVuImage::get_bgpm() const
00284 {
00285    if (file)
00286      return get_bgpm(file);
00287    else
00288      return 0;
00289 }
00290 
00291 GP<JB2Image>   
00292 DjVuImage::get_fgjb() const
00293 {
00294    if (file)
00295      return get_fgjb(file);
00296    else
00297      return 0;
00298 }
00299 
00300 GP<GPixmap>    
00301 DjVuImage::get_fgpm() const
00302 {
00303    if (file)
00304      return get_fgpm(file);
00305    else
00306      return 0;
00307 }
00308 
00309 GP<DjVuPalette>    
00310 DjVuImage::get_fgbc() const
00311 {
00312    if (file)
00313      return get_fgbc(file);
00314    else
00315      return 0;
00316 }
00317 
00318 int
00319 DjVuImage::get_width() const
00320 {
00321    GP<DjVuInfo> info=get_info();
00322    return info?((rotate_count&1)?(info->height):(info->width)):0;
00323 }
00324 
00325 int
00326 DjVuImage::get_height() const
00327 {
00328    GP<DjVuInfo> info=get_info();
00329    return info?((rotate_count&1)?(info->width):(info->height)):0;
00330 }
00331 
00332 int
00333 DjVuImage::get_real_width() const
00334 {
00335    GP<DjVuInfo> info=get_info();
00336    return info ? info->width : 0;
00337 }
00338 
00339 int
00340 DjVuImage::get_real_height() const
00341 {
00342    GP<DjVuInfo> info=get_info();
00343    return info ? info->height : 0;
00344 }
00345 
00346 int
00347 DjVuImage::get_version() const
00348 {
00349    GP<DjVuInfo> info=get_info();
00350    return info ? info->version : DJVUVERSION;
00351 }
00352 
00353 int
00354 DjVuImage::get_dpi() const
00355 {
00356    GP<DjVuInfo> info=get_info();
00357    return info ? info->dpi : 300;
00358 }
00359 
00360 int
00361 DjVuImage::get_rounded_dpi() const
00362 {
00363    return (get_dpi()+5)/10*10;
00364 #if 0   
00365       /* This code used to round the reported dpi to 25, 50, 75, 100, 150,
00366      300, and 600. Now we just round the dpi to 10ths and return it */
00367    int dpi=get_dpi();
00368    if (dpi>700) return dpi;
00369   
00370    const int std_dpi[]={ 25, 50, 75, 100, 150, 300, 600 };
00371    const int std_dpis=sizeof(std_dpi)/sizeof(std_dpi[0]);
00372    int min_dist=abs(dpi-std_dpi[0]);
00373    int min_idx=0;
00374    for(int i=1;i<std_dpis;i++)
00375       if (abs(std_dpi[i]-dpi)<min_dist)
00376       {
00377          min_dist=abs(std_dpi[i]-dpi);
00378          min_idx=i;
00379       };
00380    return std_dpi[min_idx];
00381 #endif
00382 }
00383 
00384 double
00385 DjVuImage::get_gamma() const
00386 {
00387    GP<DjVuInfo> info=get_info();
00388    return info ? info->gamma : 2.2;
00389 }
00390 
00391 GUTF8String
00392 DjVuImage::get_mimetype() const
00393 {
00394    return file ? file->mimetype : GUTF8String();
00395 }
00396 
00397 
00399 
00400 GUTF8String 
00401 DjVuImage::get_short_description() const
00402 {
00403   GUTF8String msg = "Empty";
00404   int width = get_width();
00405   int height = get_height();
00406   if (width && height)
00407     if (file && file->file_size>100)
00408       //msg.format("%dx%d in %0.1f Kb", width, height, file->file_size/1024.0);
00409       msg.format( ERR_MSG("DjVuImage.short1") "\t%d\t%d\t%0.1f", width, height, file->file_size/1024.0 );
00410     else
00411       //msg.format("%dx%d", width, height);
00412       msg.format( ERR_MSG("DjVuImage.short2") "\t%d\t%d", width, height );
00413   return msg;
00414 }
00415 
00416 GUTF8String 
00417 DjVuImage::get_long_description() const
00418 {
00419   return file?(file->description):GUTF8String();
00420 }
00421 
00422 
00423 void
00424 DjVuImage::notify_chunk_done(const DjVuPort *, const GUTF8String & name)
00425 {
00426    if (!relayout_sent &&
00427      ( !name.cmp("INFO", 4) ||
00428        !name.cmp("PMxx", 2) ||
00429        !name.cmp("BMxx", 2)  ) )
00430    {
00431       DjVuPort::get_portcaster()->notify_relayout(this);
00432       relayout_sent=true;
00433    } 
00434    else if (!name.cmp("Sxxx", 1) ||
00435             !name.cmp("BGxx", 2) ||
00436             !name.cmp("FGxx", 2) ||
00437             !name.cmp("BMxx", 2) ||
00438             !name.cmp("PMxx", 2)  )
00439      DjVuPort::get_portcaster()->notify_redisplay(this);
00440 }
00441 
00442 
00443 
00444 
00445 
00446 
00448 
00449 DjVuInterface::~DjVuInterface() 
00450 {
00451 }
00452 
00453 class DjVuImageNotifier : public DjVuPort
00454 {
00455   friend class DjVuImage;
00456   DjVuInterface  *notifier;
00457   GP<DataPool>    stream_pool;
00458   GURL        stream_url;
00459 public:
00460   DjVuImageNotifier(DjVuInterface *notifier);
00461   GP<DataPool> request_data(const DjVuPort *src, const GURL & url);
00462   void notify_chunk_done(const DjVuPort *, const GUTF8String &name);
00463   void notify_redisplay(const class DjVuImage * source);
00464   void notify_relayout(const class DjVuImage * source);
00465 };
00466 
00467 DjVuImageNotifier::DjVuImageNotifier(DjVuInterface *notifier)
00468   : notifier(notifier)
00469 {
00470 }
00471 
00472 GP<DataPool> 
00473 DjVuImageNotifier::request_data(const DjVuPort *src, const GURL & url)
00474 {
00475   if (url!=stream_url)
00476     G_THROW( ERR_MSG("DjVuImage.not_decode") );
00477   return stream_pool;
00478 }
00479 
00480 void 
00481 DjVuImageNotifier::notify_redisplay(const class DjVuImage * source)
00482 {
00483   if (notifier)
00484     notifier->notify_redisplay();
00485 }
00486 
00487 void 
00488 DjVuImageNotifier::notify_relayout(const class DjVuImage * source)
00489 {
00490   if (notifier)
00491     notifier->notify_relayout();
00492 }
00493 
00494 void 
00495 DjVuImageNotifier::notify_chunk_done(const DjVuPort *, const GUTF8String &name)
00496 {
00497   if (notifier)
00498     notifier->notify_chunk(name, "" );
00499 }
00500 
00501 void
00502 DjVuImage::decode(ByteStream & str, DjVuInterface *notifier)
00503 {
00504   DEBUG_MSG("DjVuImage::decode(): decoding old way...\n");
00505   DEBUG_MAKE_INDENT(3);
00506   if (file) 
00507     G_THROW( ERR_MSG("DjVuImage.bad_call") );
00508   GP<DjVuImageNotifier> pport = new DjVuImageNotifier(notifier);
00509   pport->stream_url=GURL::UTF8("internal://fake/fake.djvu");
00510   pport->stream_pool=DataPool::create();
00511   // Get all the data first
00512   int length;
00513   char buffer[1024];
00514   while((length=str.read(buffer, 1024)))
00515     pport->stream_pool->add_data(buffer, length);
00516   pport->stream_pool->set_eof();
00517   GP<DjVuDocument> doc = DjVuDocument::create_wait(pport->stream_url, (DjVuImageNotifier*)pport);
00518   GP<DjVuImage> dimg=doc->get_page(-1, true, (DjVuImageNotifier*)pport);
00519   file=dimg->get_djvu_file();
00520   if (file->is_decode_stopped())
00521     G_THROW( DataPool::Stop );
00522   if (file->is_decode_failed())
00523     G_THROW( ByteStream::EndOfFile ); // guess
00524   if (!file->is_decode_ok())
00525     G_THROW( ERR_MSG("DjVuImage.mult_error") );
00526   DEBUG_MSG("decode DONE\n");
00527 }
00528 
00529 
00531 
00532 static int
00533 compute_red(int w, int h, int rw, int rh)
00534 {
00535   for (int red=1; red<16; red++)
00536     if (((w+red-1)/red==rw) && ((h+red-1)/red==rh))
00537       return red;
00538   return 16;
00539 }
00540 
00541 
00542 int 
00543 DjVuImage::is_legal_bilevel() const
00544 {
00545   // Components
00546   GP<DjVuInfo> info = get_info();
00547   GP<JB2Image> fgjb = get_fgjb();
00548   GP<IW44Image> bg44 = get_bg44();
00549   GP<GPixmap>  bgpm = get_bgpm();
00550   GP<GPixmap>  fgpm = get_fgpm();
00551   // Check info
00552   if (! info)
00553     return 0;
00554   int width = info->width;
00555   int height = info->height;
00556   if (! (width>0 && height>0))
00557     return 0;
00558   // Check fgjb
00559   if (!fgjb)
00560     return 0;
00561   if (fgjb->get_width()!=width || fgjb->get_height()!=height)
00562     return 0;
00563   // Check that color information is not present.
00564   if (bg44 || bgpm || fgpm)
00565     return 0;
00566   // Ok.
00567   return 1;
00568 }
00569 
00570 int 
00571 DjVuImage::is_legal_photo() const
00572 {
00573   // Components
00574   GP<DjVuInfo> info = get_info();
00575   GP<JB2Image> fgjb = get_fgjb(); 
00576   GP<IW44Image> bg44 = get_bg44();
00577   GP<GPixmap>  bgpm = get_bgpm();
00578   GP<GPixmap>  fgpm = get_fgpm();
00579   // Check info
00580   if (! info)
00581     return 0;
00582   int width = info->width;
00583   int height = info->height;
00584   if (! (width>0 && height>0))
00585     return 0;
00586   // Check that extra information is not present.
00587   if (fgjb || fgpm)
00588     return 0;
00589   // Check bg44
00590   if (bg44 && bg44->get_width()==width && bg44->get_height()==height)
00591     return 1;
00592   // Check bgpm
00593   if (bgpm && (int)bgpm->columns()==width && (int)bgpm->rows()==height)
00594     return 1;
00595   // Ok.
00596   return 0;
00597 }
00598 
00599 int 
00600 DjVuImage::is_legal_compound() const
00601 {
00602   // Components
00603   GP<DjVuInfo>     info = get_info();
00604   GP<JB2Image>     fgjb = get_fgjb();
00605   GP<IW44Image>     bg44 = get_bg44();
00606   GP<GPixmap>      bgpm = get_bgpm();
00607   GP<GPixmap>      fgpm = get_fgpm();
00608   GP<DjVuPalette>  fgbc = get_fgbc();
00609   // Check size
00610   if (! info)
00611     return 0;
00612   int width = info->width;
00613   int height = info->height;
00614   if (! (width>0 && height>0))
00615     return 0;
00616   // Check fgjb
00617   if (!fgjb)
00618     return 0;
00619   if (fgjb->get_width()!=width || fgjb->get_height()!=height)
00620     return 0;
00621   // Check background
00622   int bgred = 0;
00623   if (bg44)
00624     bgred = compute_red(width, height, bg44->get_width(), bg44->get_height());
00625   else if (bgpm)
00626     bgred = compute_red(width, height, bgpm->columns(), bgpm->rows());
00627   if (bgred<1 || bgred>12)
00628     return 0;
00629   // Check foreground colors
00630   int fgred = 0;
00631   if (fgbc)
00632     fgred = 1;
00633   else if (fgpm)
00634     fgred = compute_red(width, height, fgpm->columns(), fgpm->rows());
00635   if (fgred<1 || fgred>12)
00636     return 0;
00637   // Check that all components are present
00638   if (fgjb && bgred && fgred)
00639     return 1;
00640   // Unrecognized
00641   return 0;
00642 }
00643 
00644 
00646 
00647 GP<GBitmap>
00648 DjVuImage::get_bitmap(const GRect &rect, 
00649                       int subsample, int align) const
00650 {
00651   // Access image size
00652   int width = get_real_width();
00653   int height = get_real_height();
00654   GP<JB2Image> fgjb = get_fgjb();
00655   if ( width && height && fgjb && 
00656        (fgjb->get_width() == width) && 
00657        (fgjb->get_height() == height) ) 
00658     {
00659       return fgjb->get_bitmap(rect, subsample, align);
00660     }
00661   return 0;
00662 }
00663 
00664 GP<GPixmap>
00665 DjVuImage::get_bg_pixmap(const GRect &rect, 
00666                          int subsample, double gamma) const
00667 {
00668   GP<GPixmap> pm = 0;
00669   // Access image size
00670   
00671   GP<DjVuInfo> info = get_info();
00672   int width = get_real_width();
00673   int height = get_real_height();
00674 
00675 
00676   if (width<=0 || height<=0 || !info) return 0;
00677   // Compute gamma_correction
00678   double gamma_correction = 1.0;
00679   if (gamma > 0)
00680     gamma_correction = gamma / info->gamma;
00681   if (gamma_correction < 0.1)
00682     gamma_correction = 0.1;
00683   else if (gamma_correction > 10)
00684     gamma_correction = 10;
00685   
00686   // CASE1: Incremental BG IW44Image
00687   GP<IW44Image> bg44 = get_bg44();
00688   if (bg44)
00689     {
00690       int w = bg44->get_width();
00691       int h = bg44->get_height();
00692       // Avoid silly cases
00693       if (w==0 || h==0 || width==0 || height==0)
00694         return 0;
00695       // Determine how much bg44 is reduced
00696       int red = compute_red(width,height,w,h);
00697       if (red<1 || red>12)
00698         return 0;
00699       // Handle pure downsampling cases
00700       if (subsample == red)
00701         pm = bg44->get_pixmap(1,rect);
00702       else if (subsample == 2*red)
00703         pm = bg44->get_pixmap(2,rect);    
00704       else if (subsample == 4*red)
00705         pm = bg44->get_pixmap(4,rect); 
00706       else if (subsample == 8*red)
00707         pm = bg44->get_pixmap(8,rect); 
00708       // Handle fractional downsampling case
00709       else if (red*4 == subsample*3)
00710         {
00711           GRect nrect = rect;
00712           GRect xrect = rect;
00713           xrect.xmin = (xrect.xmin/3)*4;
00714           xrect.ymin = (xrect.ymin/3)*4;
00715           xrect.xmax = ((xrect.xmax+2)/3)*4;
00716           xrect.ymax = ((xrect.ymax+2)/3)*4;
00717           nrect.translate(-xrect.xmin*3/4, -xrect.ymin*3/4);
00718           if (xrect.xmax > w) 
00719             xrect.xmax = w;
00720           if (xrect.ymax > h) 
00721             xrect.ymax = h;
00722           GP<GPixmap> ipm = bg44->get_pixmap(1,xrect);
00723           pm = GPixmap::create();
00724           pm->downsample43(ipm, &nrect);
00725         }
00726       // Handle all other cases with pixmapscaler
00727       else
00728         {
00729           // find suitable power of two
00730           int po2 = 16;
00731           while (po2>1 && subsample<po2*red)
00732             po2 >>= 1;
00733           // setup pixmap scaler
00734           int inw = (w+po2-1)/po2;
00735           int inh = (h+po2-1)/po2;
00736           int outw = (width+subsample-1)/subsample;
00737           int outh = (height+subsample-1)/subsample;
00738           GP<GPixmapScaler> gps=GPixmapScaler::create(inw, inh, outw, outh);
00739           GPixmapScaler &ps=*gps;
00740           ps.set_horz_ratio(red*po2, subsample);
00741           ps.set_vert_ratio(red*po2, subsample);
00742           // run pixmap scaler
00743           GRect xrect;
00744           ps.get_input_rect(rect,xrect);
00745           GP<GPixmap> ipm = bg44->get_pixmap(po2,xrect);
00746           pm = GPixmap::create();
00747           ps.scale(xrect, *ipm, rect, *pm);
00748         }
00749       // Apply gamma correction
00750       if (pm && gamma_correction!=1.0)
00751         pm->color_correct(gamma_correction);
00752       return pm;
00753     }
00754 
00755   // CASE 2: Raw background pixmap
00756   GP<GPixmap>  bgpm = get_bgpm();
00757   if (bgpm)
00758     {
00759       int w = bgpm->columns();
00760       int h = bgpm->rows();
00761       // Avoid silly cases
00762       if (w==0 || h==0 || width==0 || height==0)
00763         return 0;
00764       // Determine how much bgpm is reduced
00765       int red = compute_red(width,height,w,h);
00766       if (red<1 || red>12)
00767         return 0;
00768       // Handle pure downsampling cases
00769       int ratio = subsample/red;
00770       if (subsample==ratio*red && ratio>=1)
00771         {
00772           pm = GPixmap::create();
00773           if (ratio == 1)
00774             pm->init(*bgpm, rect);
00775           else if (ratio > 1)
00776             pm->downsample(bgpm, ratio, &rect);
00777         }
00778       // Handle all other cases with pixmapscaler
00779       else
00780         {
00781           // setup pixmap scaler
00782           int outw = (width+subsample-1)/subsample;
00783           int outh = (height+subsample-1)/subsample;
00784           GP<GPixmapScaler> gps=GPixmapScaler::create(w, h, outw, outh);
00785           GPixmapScaler &ps=*gps;
00786           ps.set_horz_ratio(red, subsample);
00787           ps.set_vert_ratio(red, subsample);
00788           // run pixmap scaler
00789           pm = GPixmap::create();
00790           GRect xrect(0,0,w,h);
00791           ps.scale(xrect, *bgpm, rect, *pm);
00792         }
00793       // Apply gamma correction
00794       if (pm && gamma_correction!=1.0)
00795         pm->color_correct(gamma_correction);
00796       return pm;
00797     }
00798 
00799   // FAILURE
00800   return 0;
00801 }
00802 
00803 
00804 
00805 int  
00806 DjVuImage::stencil(GPixmap *pm, const GRect &rect,
00807            int subsample, double gamma) const
00808 {
00809   // Warping and blending. 
00810   if (!pm)
00811     return 0;
00812   // Access components
00813   
00814   GP<DjVuInfo> info = get_info();
00815   int width = get_real_width();
00816   int height = get_real_height();
00817 
00818 
00819   if (width<=0 || height<=0 || !info) return 0;
00820   GP<JB2Image> fgjb = get_fgjb();
00821   GP<GPixmap> fgpm = get_fgpm();
00822   GP<DjVuPalette> fgbc = get_fgbc();
00823   
00824   // Compute gamma_correction
00825   double gamma_correction = 1.0;
00826   if (gamma > 0)
00827     gamma_correction = gamma / info->gamma;
00828   if (gamma_correction < 0.1)
00829     gamma_correction = 0.1;
00830   else if (gamma_correction > 10)
00831     gamma_correction = 10;
00832 
00833   // Compute alpha map and relevant JB2Image components
00834   GList<int> components;
00835   GP<GBitmap> bm;
00836   if (fgjb)
00837     {
00838       JB2Image *jimg = fgjb;
00839       if (! (width && height && 
00840              jimg->get_width() == width && 
00841              jimg->get_height() == height ) )
00842         return 0;
00843       // Decode bitmap
00844       bm = GBitmap::create(rect.height(), rect.width());
00845       bm->set_grays(1+subsample*subsample);
00846       int rxmin = rect.xmin * subsample;
00847       int rymin = rect.ymin * subsample;
00848       for (int blitno = 0; blitno < jimg->get_blit_count(); blitno++)
00849         {
00850           const JB2Blit *pblit = jimg->get_blit(blitno);
00851           const JB2Shape  &pshape = jimg->get_shape(pblit->shapeno);
00852           if (pshape.bits &&
00853               pblit->left <= rect.xmax * subsample &&
00854               pblit->bottom <= rect.ymax * subsample &&
00855               pblit->left + (int)pshape.bits->columns() >= rect.xmin * subsample &&
00856               pblit->bottom + (int)pshape.bits->rows() >= rect.ymin * subsample )
00857             {
00858               // Record component list
00859               if (fgbc) components.append(blitno);
00860               // Blit
00861               bm->blit(pshape.bits, 
00862                        pblit->left - rxmin, pblit->bottom - rymin, 
00863                        subsample);
00864             }
00865         }
00866     }
00867 
00868 
00869   // TWO LAYER MODEL
00870   if (bm && fgbc)
00871     {
00872       // Perform attenuation from scratch
00873       pm->attenuate(bm, 0, 0);
00874       // Check that fgbc has the correct size
00875       JB2Image *jimg = fgjb;
00876       DjVuPalette *fg = fgbc;
00877       if (jimg->get_blit_count() != fg->colordata.size())
00878         return 0;
00879       // Copy and color correct palette
00880       int palettesize = fg->size();
00881       GTArray<GPixel> colors(0,palettesize-1);
00882       for (int i=0; i<palettesize; i++)
00883         fg->index_to_color(i, colors[i]);
00884       GPixmap::color_correct(gamma_correction, colors, palettesize);
00885       // Blit all components (one color at a time)
00886       while (components.size() > 0)
00887         {
00888           GPosition nullpos;
00889           GPosition pos = components;
00890           int lastx = 0;
00891           int colorindex = fg->colordata[components[pos]];
00892           if (colorindex >= palettesize)
00893             G_THROW( ERR_MSG("DjVuImage.corrupted") );
00894           // Gather relevant components and relevant rectangle
00895           GList<int> compset;
00896           GRect comprect;
00897           while (pos)
00898             {
00899               int blitno = components[pos];
00900               const JB2Blit *pblit = jimg->get_blit(blitno);
00901               if (pblit->left < lastx) break; 
00902               lastx = pblit->left;
00903               if (fg->colordata[blitno] == colorindex)
00904                 {
00905                   const JB2Shape  &pshape = jimg->get_shape(pblit->shapeno);
00906                   GRect rect(pblit->left, pblit->bottom, 
00907                              pshape.bits->columns(), pshape.bits->rows());
00908                   comprect.recthull(comprect, rect);
00909                   compset.insert_before(nullpos, components, pos);
00910                   continue;
00911                 }
00912               ++pos;
00913             }
00914           // Round alpha map rectangle
00915           comprect.xmin = comprect.xmin / subsample;
00916           comprect.ymin = comprect.ymin / subsample;
00917           comprect.xmax = (comprect.xmax+subsample-1) / subsample;
00918           comprect.ymax = (comprect.ymax+subsample-1) / subsample;
00919           comprect.intersect(comprect, rect);
00920           // Compute alpha map for that color
00921           bm = 0;
00922           bm = GBitmap::create(comprect.height(), comprect.width());
00923           bm->set_grays(1+subsample*subsample);
00924           int rxmin = comprect.xmin * subsample;
00925           int rymin = comprect.ymin * subsample;
00926           for (pos=compset; pos; ++pos)
00927             {
00928               int blitno = compset[pos];
00929               const JB2Blit *pblit = jimg->get_blit(blitno);
00930               const JB2Shape  &pshape = jimg->get_shape(pblit->shapeno);
00931               bm->blit(pshape.bits, 
00932                        pblit->left - rxmin, pblit->bottom - rymin, 
00933                        subsample);
00934             }
00935           // Blend color into background pixmap
00936           pm->blit(bm, comprect.xmin-rect.xmin, comprect.ymin-rect.ymin, &colors[colorindex]);
00937         }
00938       return 1;
00939     }
00940 
00941 
00942   // THREE LAYER MODEL
00943   if (bm && fgpm)
00944     {
00945       // This follows fig. 4 in Adelson "Layered representations for image
00946       // coding" (1991) http://www-bcs.mit.edu/people/adelson/papers.html.
00947       // The properly warped background is already in PM.  The properly warped
00948       // alpha map is already in BM.  We just have to warp the foreground and
00949       // perform alpha blending.
00950 #ifdef SIMPLE_THREE_LAYER_RENDERING
00951       int w = fgpm->columns();
00952       int h = fgpm->rows();
00953       // Determine foreground reduction
00954       int red = compute_red(width,height, w, h);
00955       if (red<1 || red>12)
00956         return 0;
00957       // Warp foreground pixmap
00958       GPixmapScaler ps(w,h,width/subsample+1,height/subsample+1);
00959       ps.set_horz_ratio(red,subsample);
00960       ps.set_vert_ratio(red,subsample);
00961       GP<GPixmap> nfg = new GPixmap;
00962       GRect provided(0,0,w,h);
00963       ps.scale(provided, *fgpm, rect, *nfg);
00964       // Attenuate background and blit
00965       nfg->color_correct(gamma_correction);
00966       pm->blend(bm, 0, 0, nfg); // blend == attenuate + blit
00967       return 1;
00968 #else 
00969       // Things are now a little bit more complex because the convenient
00970       // function GPixmap::stencil() simultaneously upsamples the foreground 
00971       // by an integer factor and performs the alpha blending.  We have
00972       // to determine how and when this facility can be used.
00973       int w = fgpm->columns();
00974       int h = fgpm->rows();
00975       // Determine foreground reduction
00976       int red = compute_red(width,height,w,h);
00977       if (red<1 || red>12)
00978         return 0;
00979       // Try supersampling foreground pixmap by an integer factor
00980       int supersample = ( red>subsample ? red/subsample : 1);
00981       int wantedred = supersample*subsample;
00982       // Try simple foreground upsampling
00983       if (red == wantedred)
00984         {
00985           // Simple foreground upsampling is enough.
00986           pm->stencil(bm, fgpm, supersample, &rect, gamma_correction);
00987           return 1;
00988         }
00989       else 
00990         {
00991           // Must pre-warp foreground pixmap
00992           GP<GPixmap> nfg;
00993           int desw = (w*red+wantedred-1)/wantedred;
00994           int desh = (h*red+wantedred-1)/wantedred;
00995           // Cache rescaled fgpm for speed
00996           static const DjVuImage *tagimage  = 0;
00997           static const GPixmap *tagfgpm   = 0;
00998           static GP<GPixmap> cachednfg = 0;
00999           // Check whether cached fgpm applies.
01000           if ( cachednfg && this==tagimage && fgpm==tagfgpm
01001                && desw==(int)cachednfg->columns()
01002                && desh==(int)cachednfg->rows() )
01003             {
01004               nfg = cachednfg;
01005             }
01006           else
01007             {
01008               GP<GPixmapScaler> gps=GPixmapScaler::create(w,h,desw,desh);
01009               GPixmapScaler &ps=*gps;
01010               ps.set_horz_ratio(red, wantedred);
01011               ps.set_vert_ratio(red, wantedred);
01012               nfg = GPixmap::create();
01013               GRect provided(0,0,w,h);
01014               GRect desired(0,0,desw,desh);
01015               ps.scale(provided, *fgpm, desired, *nfg);
01016             }
01017           // Use combined warp+blend function
01018           pm->stencil(bm, nfg, supersample, &rect, gamma_correction);
01019           // Cache
01020           tagimage = this;
01021           tagfgpm = fgpm;
01022           cachednfg = nfg;
01023           return 1;
01024         }
01025 #endif
01026     }
01027   
01028   // FAILURE
01029   return 0;
01030 }
01031 
01032 
01033 GP<GPixmap>
01034 DjVuImage::get_fg_pixmap(const GRect &rect, 
01035                          int subsample, double gamma) const
01036 {
01037   // Obtain white background pixmap
01038   GP<GPixmap> pm;
01039   // Access components
01040   const int width = get_real_width();
01041   const int height = get_real_height();
01042   if (width && height)
01043   {
01044     pm = GPixmap::create(rect.height(),rect.width(), &GPixel::WHITE);
01045     if (!stencil(pm, rect, subsample, gamma))
01046       pm=0;
01047   }
01048   return pm;
01049 }
01050 
01051 
01052 GP<GPixmap>
01053 DjVuImage::get_pixmap(const GRect &rect, int subsample, double gamma) const
01054 {
01055   // Get background
01056   GP<GPixmap> pm = get_bg_pixmap(rect, subsample, gamma);
01057   // Superpose foreground
01058   if (! stencil(pm, rect, subsample, gamma))
01059     // Avoid ugly progressive display (hack)
01060     if (get_fgjb()) return 0;
01061   // Return
01062   return pm;
01063 }
01064 
01065 
01067 
01068 typedef GP<GBitmap>(DjVuImage::*BImager)(const GRect &, int, int) const;
01069 typedef GP<GPixmap>(DjVuImage::*PImager)(const GRect &, int, double) const;
01070 
01071 static GP<GBitmap>
01072 do_bitmap(const DjVuImage &dimg, BImager get,
01073           const GRect &inrect, const GRect &inall, int align )
01074 {
01075     GRect rect=inrect;
01076     GRect all=inall;
01078     if( dimg.get_rotate()%4 )
01079     {
01080         GRectMapper mapper;
01081         mapper.rotate((4-dimg.get_rotate())%4);
01082         mapper.map(rect);
01083         mapper.map(all);
01084     }
01086 
01087   // Sanity
01088   if (! ( all.contains(rect.xmin, rect.ymin) &&
01089           all.contains(rect.xmax-1, rect.ymax-1) ))
01090     G_THROW( ERR_MSG("DjVuImage.bad_rect") );
01091   // Check for integral reduction
01092   int red;
01093   int w = dimg.get_real_width();
01094   int h = dimg.get_real_height();
01095 
01096   int rw = all.width();
01097   int rh = all.height();
01098   GRect zrect = rect; 
01099   zrect.translate(-all.xmin, -all.ymin);
01100   for (red=1; red<=15; red++)
01101     if (rw*red>w-red && rw*red<w+red && rh*red>h-red && rh*red<h+red)
01102     {
01103         GP<GBitmap> bm=(dimg.*get)(zrect, red, align);
01104         if(bm)
01105             return bm->rotate((4-dimg.get_rotate())%4);
01106         else
01107             return NULL;
01108     }
01109   // Find best reduction
01110   for (red=15; red>1; red--)
01111     if ( (rw*red < w && rh*red < h) ||
01112          (rw*red*3 < w || rh*red*3 < h) )
01113       break;
01114   // Setup bitmap scaler
01115   if (! (w && h)) return 0;
01116   GP<GBitmapScaler> gbs=GBitmapScaler::create();
01117   GBitmapScaler &bs=*gbs;
01118   bs.set_input_size( (w+red-1)/red, (h+red-1)/red );
01119   bs.set_output_size( rw, rh );
01120   bs.set_horz_ratio( rw*red, w );
01121   bs.set_vert_ratio( rh*red, h );
01122   // Scale
01123   GRect srect;
01124   bs.get_input_rect(zrect, srect);
01125   GP<GBitmap> sbm = (dimg.*get)(srect, red, 1);
01126   if (!sbm) return 0;
01127   int border = ((zrect.width() + align - 1) & ~(align - 1)) - zrect.width();
01128   GP<GBitmap> bm = GBitmap::create(zrect.height(), zrect.width(), border);
01129   bs.scale(srect, *sbm, zrect, *bm);
01130   if( bm )
01131       return bm->rotate((4-dimg.get_rotate())%4);
01132   else
01133       return NULL;
01134 }
01135 
01136 static GP<GPixmap>
01137 do_pixmap(const DjVuImage &dimg, PImager get,
01138           const GRect &inrect, const GRect &inall, double gamma )
01139 {
01140 
01141     GRect rect=inrect;
01142     GRect all=inall;
01144     if( dimg.get_rotate()%4 )
01145     {
01146         GRectMapper mapper;
01147         mapper.rotate((4-dimg.get_rotate())%4);
01148         mapper.map(rect);
01149         mapper.map(all);
01150     }
01152 
01153   // Sanity
01154   if (! ( all.contains(rect.xmin, rect.ymin) &&
01155           all.contains(rect.xmax-1, rect.ymax-1) ))
01156     G_THROW( ERR_MSG("DjVuImage.bad_rect2") );
01157   // Check for integral reduction
01158   int red, w=0, h=0, rw=0, rh=0;
01159   w = dimg.get_real_width();
01160   h = dimg.get_real_height();
01161   
01162 
01163   rw = all.width();
01164   rh = all.height();
01165   GRect zrect = rect; 
01166   zrect.translate(-all.xmin, -all.ymin);
01167   for (red=1; red<=15; red++)
01168     if (rw*red>w-red && rw*red<w+red && rh*red>h-red && rh*red<h+red)
01169     {
01170         GP<GPixmap> pm = (dimg.*get)(zrect, red, gamma);
01171         if( pm ) 
01172             return pm->rotate((4-dimg.get_rotate())%4);
01173         else
01174             return NULL;
01175     }
01176   // These reductions usually go faster (improve!)
01177   static int fastred[] = { 12,6,4,3,2,1 };
01178   // Find best reduction
01179   for (int i=0; (red=fastred[i])>1; i++)
01180     if ( (rw*red < w && rh*red < h) ||
01181          (rw*red*3 < w || rh*red*3 < h) )
01182       break;
01183   // Setup pixmap scaler
01184   if (w<0 || h<0) return 0;
01185   GP<GPixmapScaler> gps=GPixmapScaler::create();
01186   GPixmapScaler &ps=*gps;
01187   ps.set_input_size( (w+red-1)/red, (h+red-1)/red );
01188   ps.set_output_size( rw, rh );
01189   ps.set_horz_ratio( rw*red, w );
01190   ps.set_vert_ratio( rh*red, h );
01191   // Scale
01192   GRect srect;
01193   ps.get_input_rect(zrect, srect);
01194   GP<GPixmap> spm = (dimg.*get)(srect, red, gamma);
01195   if (!spm) return 0;
01196   GP<GPixmap> pm = GPixmap::create();
01197   ps.scale(srect, *spm, zrect, *pm);
01198   if(pm)
01199       return pm->rotate((4-dimg.get_rotate())%4);
01200   else
01201       return NULL;
01202 }
01203 
01204 GP<GPixmap>  
01205 DjVuImage::get_pixmap(const GRect &rect, const GRect &all, double gamma) const
01206 {
01207   return do_pixmap(*this, & DjVuImage::get_pixmap, rect, all, gamma);
01208 }
01209 
01210 GP<GBitmap>  
01211 DjVuImage::get_bitmap(const GRect &rect, const GRect &all, int align) const
01212 {
01213   return do_bitmap(*this, & DjVuImage::get_bitmap, rect, all, align);
01214 }
01215 
01216 GP<GPixmap>  
01217 DjVuImage::get_bg_pixmap(const GRect &rect, const GRect &all, double gamma) const
01218 {
01219   return do_pixmap(*this, & DjVuImage::get_bg_pixmap, rect, all, gamma);
01220 }
01221 
01222 GP<GPixmap>  
01223 DjVuImage::get_fg_pixmap(const GRect &rect, const GRect &all, double gamma) const
01224 {
01225   return do_pixmap(*this, & DjVuImage::get_fg_pixmap, rect, all, gamma);
01226 }
01227 
01228 int 
01229 DjVuImage::get_rotate() const
01230 {
01231   return (rotate_count<0)?0:rotate_count;
01232 }
01233 
01234 void
01235 DjVuImage::init_rotate(const DjVuInfo &info)
01236 { 
01237   rotate_count=((360-GRect::findangle(info.orientation))/90)%4;
01238 }
01239 
01240 void DjVuImage::set_rotate(int count) 
01241 { 
01242   rotate_count=((count%4)+4)%4;
01243 }
01244 
01245 GP<DjVuAnno> 
01246 DjVuImage::get_decoded_anno()
01247 {
01248     GP<DjVuAnno> djvuanno = DjVuAnno::create();
01249     GP<ByteStream> bs=get_anno();
01250     if( bs )
01251     {
01252         djvuanno->decode(bs);
01253        
01254         const int rotate_count=get_rotate(); 
01255         if( rotate_count % 4 )
01256         {   
01258             GRect input, output;
01259             input = GRect(0,0,get_width(), get_height());
01260             output = GRect(0,0,  get_real_width(), get_real_height());
01261 
01262             GRectMapper mapper;
01263             mapper.clear();
01264             mapper.set_input(input);
01265             mapper.set_output(output);               
01266             mapper.rotate((4-rotate_count)%4);
01267 
01268             GPList<GMapArea> &list=djvuanno->ant->map_areas;
01269             for(GPosition pos=list;pos;++pos)
01270             {
01271                 list[pos]->unmap(mapper);
01272             }
01273         }
01274         return djvuanno;
01275     }
01276     else
01277         return NULL;
01278 }
01279 
01280 
01281 void
01282 DjVuImage::map(GRect &rect) const
01283 {
01284     GRect input, output;
01285     const int rotate_count=get_rotate(); 
01286     if(rotate_count%4)
01287     {  
01288         input = GRect(0,0,get_width(), get_height());
01289         output = GRect(0,0, get_real_width(), get_real_height());
01290 
01291         GRectMapper mapper;
01292         mapper.clear();
01293         mapper.set_input(input);
01294         mapper.set_output(output);               
01295         mapper.rotate((4-rotate_count)%4);
01296         mapper.map(rect);
01297     }
01298 }
01299 
01300 void
01301 DjVuImage::unmap(GRect &rect) const
01302 {
01303     GRect input, output;
01304     const int rotate_count=get_rotate(); 
01305     if(rotate_count%4)
01306     {  
01307         input = GRect(0,0,get_width(), get_height());
01308         output = GRect(0,0, get_real_width(), get_real_height());
01309 
01310         GRectMapper mapper;
01311         mapper.clear();
01312         mapper.set_input(input);
01313         mapper.set_output(output);               
01314         mapper.rotate((4-rotate_count)%4);
01315         mapper.unmap(rect);
01316     }
01317 }
01318 
01319 void
01320 DjVuImage::map(int &x, int &y) const
01321 {
01322     GRect input, output;
01323     const int rotate_count=get_rotate(); 
01324     if(rotate_count%4)
01325     {  
01326         input = GRect(0,0,get_width(), get_height());
01327         output = GRect(0,0, get_real_width(), get_real_height());
01328 
01329         GRectMapper mapper;
01330         mapper.clear();
01331         mapper.set_input(input);
01332         mapper.set_output(output);               
01333         mapper.rotate((4-rotate_count)%4);
01334         mapper.map(x, y);
01335     }
01336 }
01337 
01338 void
01339 DjVuImage::unmap(int &x, int &y) const
01340 {
01341     GRect input, output;
01342     const int rotate_count=get_rotate(); 
01343     if(rotate_count%4)
01344     {  
01345         input = GRect(0,0,get_width(), get_height());
01346         output = GRect(0,0, get_real_width(), get_real_height());
01347 
01348         GRectMapper mapper;
01349         mapper.clear();
01350         mapper.set_input(input);
01351         mapper.set_output(output);               
01352         mapper.rotate((4-rotate_count)%4);
01353         mapper.unmap(x, y);
01354     }
01355 }
01356 
01357 bool
01358 DjVuImage::wait_for_complete_decode(void)
01359 {
01360   if (file) 
01361   {
01362     file->resume_decode(true);
01363     return file->is_decode_ok();
01364   }
01365   return 0;
01366 }
01367 
01368 // Write out a DjVuXML object tag and map tag.
01369 void
01370 DjVuImage::writeXML(ByteStream &str_out,const GURL &doc_url,const int flags) const
01371 {
01372   const int height=get_height();
01373   
01374   static const char *Object="<OBJECT data=\"";
01375   const GURL url(get_djvu_file()->get_url());
01376   const GUTF8String pagename(url.fname());
01377   GUTF8String page_param;
01378   if(doc_url.is_valid() && !doc_url.is_empty() && (doc_url != url))
01379   {
01380     str_out.writestring(Object+doc_url.get_string());
01381     page_param="<PARAM name=\"PAGE\" value=\""+pagename+"\" />\n";
01382   }else
01383   {
01384     str_out.writestring(Object+doc_url.get_string());
01385   }
01386   str_out.writestring("\" type=\""+get_mimetype()+"\" height=\""
01387     +GUTF8String(height)+"\" width=\""+GUTF8String(get_width())
01388     +"\" usemap=\""+pagename.toEscaped()+"\" >\n");
01389   if(!(flags & NOINFO))
01390   {
01391     const GP<DjVuInfo> info(get_info());
01392     if(info)
01393     {
01394       info->writeParam(str_out);
01395     }
01396   }
01397   str_out.writestring(page_param);
01398   const GP<DjVuAnno> anno(DjVuAnno::create());
01399   if(!(flags & NOINFO)||!(flags&NOMAP))
01400   {
01401     const GP<ByteStream> anno_str(get_anno());
01402     if(anno_str)
01403     {
01404       anno->decode(anno_str);
01405     }
01406     if(!(flags & NOINFO))
01407     {
01408       anno->writeParam(str_out);
01409     }
01410   }
01411   if(!(flags & NOTEXT))
01412   {
01413     const GP<DjVuText> text(DjVuText::create());
01414     {
01415       const GP<ByteStream> text_str(get_text());
01416       if(text_str)
01417       {
01418         text->decode(text_str);
01419       }
01420       text->writeText(str_out,height);
01421     }
01422   }
01423   if(!(flags & NOMETA))
01424   {
01425     const GP<ByteStream> meta_str(get_meta());
01426     if(meta_str)
01427     {
01428       GP<IFFByteStream> giff=IFFByteStream::create(meta_str);
01429       IFFByteStream &iff=*giff;
01430       GUTF8String chkid;
01431       while( iff.get_chunk(chkid))
01432       {
01433         GP<ByteStream> gbs(iff.get_bytestream());
01434         if(chkid == "METa")
01435         {
01436        str_out.copy(*gbs);
01437           //str_out.writestring(gbs->getAsUTF8());
01438         }else if(chkid == "METz")
01439         {
01440           gbs=BSByteStream::create(gbs);
01441           str_out.copy(*gbs);
01442           //str_out.writestring(gbs->getAsUTF8());
01443         }
01444         iff.close_chunk();
01445       }
01446     }
01447   }
01448   str_out.writestring(GUTF8String("</OBJECT>\n"));
01449   if(!(flags & NOMAP))
01450   {
01451     anno->writeMap(str_out,pagename,height);
01452   }
01453 }
01454 
01455 // Write out a DjVuXML object tag and map tag.
01456 void
01457 DjVuImage::writeXML(ByteStream &str_out) const
01458 {
01459   writeXML(str_out,GURL());
01460 }
01461 
01462 // Write out a DjVuXML object tag and map tag.
01463 GUTF8String
01464 DjVuImage::get_XML(const GURL &doc_url,const int flags) const
01465 {
01466   GP<ByteStream> gbs(ByteStream::create());
01467   ByteStream &bs=*gbs;
01468   writeXML(bs,doc_url);
01469   bs.seek(0L);
01470   return bs.getAsUTF8();
01471 }
01472 
01473 // Write out a DjVuXML object tag and map tag.
01474 GUTF8String
01475 DjVuImage::get_XML(void) const
01476 {
01477   return get_XML(GURL());
01478 }
01479 
01480 
01481 #ifdef HAVE_NAMESPACES
01482 }
01483 # ifndef NOT_USING_DJVU_NAMESPACE
01484 using namespace DJVU;
01485 # endif
01486 #endif

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal