Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                         DDDD       J  V   V  U   U                          %
      7 %                         D   D      J  V   V  U   U                          %
      8 %                         D   D      J  V   V  U   U                          %
      9 %                         D   D  J   J   V V   U   U                          %
     10 %                         DDDD    JJJ     V     UUU                           %
     11 %                                                                             %
     12 %                                                                             %
     13 %                             Read DjVu Images.                               %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 July 1992                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 */
     38 
     39 /*
     41   Include declarations.
     42 */
     43 #include "MagickCore/studio.h"
     44 #include "MagickCore/blob.h"
     45 #include "MagickCore/blob-private.h"
     46 #include "MagickCore/cache.h"
     47 #include "MagickCore/colormap.h"
     48 #include "MagickCore/constitute.h"
     49 #include "MagickCore/exception.h"
     50 #include "MagickCore/exception-private.h"
     51 #include "MagickCore/image-private.h"
     52 #include "MagickCore/list.h"
     53 #include "MagickCore/magick.h"
     54 #include "MagickCore/memory_.h"
     55 #include "MagickCore/monitor.h"
     56 #include "MagickCore/monitor-private.h"
     57 #include "MagickCore/pixel-accessor.h"
     58 #include "MagickCore/quantum-private.h"
     59 #include "MagickCore/static.h"
     60 #include "MagickCore/string_.h"
     61 #include "MagickCore/module.h"
     62 #if defined(MAGICKCORE_DJVU_DELEGATE)
     63 #include <libdjvu/ddjvuapi.h>
     64 #endif
     65 
     66 /*
     68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     69 %                                                                             %
     70 %                                                                             %
     71 %                                                                             %
     72 %   I s D J V U                                                               %
     73 %                                                                             %
     74 %                                                                             %
     75 %                                                                             %
     76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     77 %
     78 %  IsDJVU() returns MagickTrue if the image format type, identified by the
     79 %  magick string, is DJVU.
     80 %
     81 %  The format of the IsDJVU method is:
     82 %
     83 %      MagickBooleanType IsDJVU(const unsigned char *magick,const size_t length)
     84 %
     85 %  A description of each parameter follows:
     86 %
     87 %    o magick: compare image format pattern against these bytes.
     88 %
     89 %    o length: Specifies the length of the magick string.
     90 %
     91 */
     92 static MagickBooleanType IsDJVU(const unsigned char *magick,const size_t length)
     93 {
     94   if (length < 8)
     95     return(MagickFalse);
     96   if (memcmp(magick,"AT&TFORM",8) == 0)
     97     return(MagickTrue);
     98   return(MagickFalse);
     99 }
    100 
    101 #if defined(MAGICKCORE_DJVU_DELEGATE)
    103 /*
    104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    105 %                                                                             %
    106 %                                                                             %
    107 %                                                                             %
    108 %   R e a d D J V U I m a g e                                                 %
    109 %                                                                             %
    110 %                                                                             %
    111 %                                                                             %
    112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    113 %
    114 %  ReadDJVUImage() reads DJVU image and returns it.  It allocates the memory
    115 %  necessary for the new Image structure and returns a pointer to the new
    116 %  image or set of images.
    117 %
    118 %  The format of the ReadDJVUImage method is:
    119 %
    120 %      Image *ReadDJVUImage(const ImageInfo *image_info,
    121 %        ExceptionInfo *exception)
    122 %
    123 %  A description of each parameter follows:
    124 %
    125 %    o image_info: the image info.
    126 %
    127 %    o exception: return any errors or warnings in this structure.
    128 %
    129 */
    130 
    131 #if defined(__cplusplus) || defined(c_plusplus)
    132 extern "C" {
    133 #endif
    134 
    135 typedef struct _LoadContext
    136    LoadContext;
    137 
    138 struct _LoadContext
    139 {
    140   ddjvu_context_t* context;
    141   ddjvu_document_t *document;
    142   ddjvu_page_t *page;
    143   int streamid;
    144   int pages;
    145   Image *image;
    146 };
    147 
    148 #define BLOCKSIZE  65536
    149 #if 0
    150 static void
    151 pump_data(Image *image, LoadContext* lc)
    152 {
    153         int blocksize = BLOCKSIZE;
    154         char data[BLOCKSIZE];
    155         int size;
    156 
    157         /* i might check for a condition! */
    158         while ((size = (size_t) ReadBlob(image,(size_t) blocksize,data)) == blocksize) {
    159                 ddjvu_stream_write(lc->document, lc->streamid, data, size);
    160         }
    161         if (size)
    162                 ddjvu_stream_write(lc->document, lc->streamid, data, size);
    163         ddjvu_stream_close(lc->document, lc->streamid, 0);
    164 }
    165 #endif
    166 
    167 /* returns NULL only after all is delivered! */
    168 static ddjvu_message_t*
    169 pump_data_until_message(LoadContext *lc,Image *image) /* ddjvu_context_t *context, type ddjvu_document_type_t */
    170 {
    171         size_t blocksize = BLOCKSIZE;
    172         unsigned char data[BLOCKSIZE];
    173         size_t size;
    174         ddjvu_message_t *message;
    175 
    176         /* i might check for a condition! */
    177         size=0;
    178         while (!(message = ddjvu_message_peek(lc->context))
    179                && (size = (size_t) ReadBlob(image,(size_t) blocksize,data)) == blocksize) {
    180                 ddjvu_stream_write(lc->document, lc->streamid, (char *) data, size);
    181         }
    182         if (message)
    183                 return message;
    184         if (size)
    185                 ddjvu_stream_write(lc->document, lc->streamid, (char *) data, size);
    186         ddjvu_stream_close(lc->document, lc->streamid, 0);
    187         return NULL;
    188 }
    189 #define DEBUG 0
    190 
    191 #if DEBUG
    192 static const char*
    193 message_tag_name(ddjvu_message_tag_t tag)
    194 {
    195    static char* names[] =
    196       {
    197          "ERROR",
    198          "INFO",
    199          "NEWSTREAM",
    200          "DOCINFO",
    201          "PAGEINFO",
    202          "RELAYOUT",
    203          "REDISPLAY",
    204          "CHUNK",
    205          "THUMBNAIL",
    206          "PROGRESS",
    207       };
    208    if (tag <= DDJVU_PROGRESS)
    209       return names[tag];
    210    else {
    211       /* bark! */
    212       return 0;
    213    }
    214 }
    215 #endif
    216 
    217 /* write out nice info on the message,
    218  * and store in *user* data the info on progress.
    219  * */
    220 int
    221 process_message(ddjvu_message_t *message)
    222 {
    223 
    224 #if 0
    225    ddjvu_context_t* context= message->m_any.context;
    226 #endif
    227 
    228    if (! message)
    229       return(-1);
    230 #if DEBUG
    231    printf("*** %s: %s.\n",__FUNCTION__, message_tag_name(message->m_any.tag));
    232 #endif
    233 
    234 
    235    switch (message->m_any.tag){
    236    case DDJVU_DOCINFO:
    237    {
    238       ddjvu_document_t* document= message->m_any.document;
    239       /* ddjvu_document_decoding_status  is set by libdjvu! */
    240       /* we have some info on the document  */
    241       LoadContext *lc = (LoadContext *) ddjvu_document_get_user_data(document);
    242       lc->pages = ddjvu_document_get_pagenum(document);
    243 #if DEBUG
    244       printf("the doc has %d pages\n", ddjvu_document_get_pagenum(document));
    245 #endif
    246       break;
    247    }
    248    case DDJVU_CHUNK:
    249 #if DEBUG
    250            printf("the name of the chunk is: %s\n", message->m_chunk.chunkid);
    251 #endif
    252            break;
    253 
    254 
    255    case DDJVU_RELAYOUT:
    256    case DDJVU_PAGEINFO:
    257    {
    258 #if 0
    259       ddjvu_page_t* page = message->m_any.page;
    260       page_info* info = ddjvu_page_get_user_data(page);
    261 
    262       printf("page decoding status: %d %s%s%s\n",
    263              ddjvu_page_decoding_status(page),
    264              status_color, status_name(ddjvu_page_decoding_status(page)), color_reset);
    265 
    266       printf("the page LAYOUT changed: width x height: %d x %d @ %d dpi. Version %d, type %d\n",
    267              // printf("page info:\n width x height: %d x %d @ %d dpi, version %d, type %d\n",
    268              ddjvu_page_get_width(page),
    269              ddjvu_page_get_height(page),
    270              ddjvu_page_get_resolution(page),
    271              ddjvu_page_get_version(page),
    272              /* DDJVU_PAGETYPE_BITONAL */
    273              ddjvu_page_get_type(page));
    274 
    275       info->info = 1;
    276 #endif
    277       break;
    278    }
    279 
    280    case DDJVU_REDISPLAY:
    281    {
    282 
    283 #if 0
    284     ddjvu_page_t* page = message->m_any.page;
    285       page_info* info = ddjvu_page_get_user_data(page);
    286 
    287       printf("the page can/should be REDISPLAYED\n");
    288       info->display = 1;
    289 #endif
    290       break;
    291    }
    292 
    293    case DDJVU_PROGRESS:
    294 #if DEBUG
    295            printf("PROGRESS:\n");
    296 #endif
    297            break;
    298    case DDJVU_ERROR:
    299            printf("simply ERROR!\n message:\t%s\nfunction:\t%s(file %s)\nlineno:\t%d\n",
    300                   message->m_error.message,
    301                   message->m_error.function,
    302                   message->m_error.filename,
    303                   message->m_error.lineno);
    304            break;
    305    case DDJVU_INFO:
    306 #if DEBUG
    307            printf("INFO: %s!\n", message->m_info.message);
    308 #endif
    309            break;
    310    default:
    311       printf("unexpected\n");
    312    };
    313   return(message->m_any.tag);
    314 }
    315 
    316 
    317 #if defined(__cplusplus) || defined(c_plusplus)
    318 }
    319 #endif
    320 
    321 
    322 #define RGB 1
    323 
    324 /*
    325  * DjVu advertised readiness to provide bitmap: So get it!
    326  * we use the RGB format!
    327  */
    328 static void
    329 get_page_image(LoadContext *lc, ddjvu_page_t *page, int x, int y, int w, int h, ExceptionInfo *exception ) {
    330   ddjvu_format_t
    331     *format;
    332 
    333   ddjvu_page_type_t
    334     type;
    335 
    336   Image
    337     *image;
    338 
    339   int
    340     ret,
    341     stride;
    342 
    343   unsigned char
    344     *q;
    345 
    346         ddjvu_rect_t rect;
    347         rect.x = x;
    348         rect.y = y;
    349         rect.w = (unsigned int) w;             /* /10 */
    350         rect.h = (unsigned int) h;             /* /10 */
    351 
    352         image = lc->image;
    353         type = ddjvu_page_get_type(lc->page);
    354 
    355         /* stride of this temporary buffer: */
    356         stride = (type == DDJVU_PAGETYPE_BITONAL)?
    357                 (image->columns + 7)/8 : image->columns *3;
    358 
    359         q = (unsigned char *) AcquireQuantumMemory(image->rows,stride);
    360         if (q == (unsigned char *) NULL)
    361           return;
    362 
    363         format = ddjvu_format_create(
    364                 (type == DDJVU_PAGETYPE_BITONAL)?DDJVU_FORMAT_LSBTOMSB : DDJVU_FORMAT_RGB24,
    365                 /* DDJVU_FORMAT_RGB24
    366                  * DDJVU_FORMAT_RGBMASK32*/
    367                 /* DDJVU_FORMAT_RGBMASK32 */
    368                 0, NULL);
    369 
    370 #if 0
    371         /* fixme:  ThrowReaderException is a macro, which uses  `exception' variable */
    372         if (format == NULL)
    373                 {
    374                         abort();
    375                         /* ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); */
    376                 }
    377 
    378 #endif
    379         ddjvu_format_set_row_order(format, 1);
    380         ddjvu_format_set_y_direction(format, 1);
    381 
    382         ret = ddjvu_page_render(page,
    383                                     DDJVU_RENDER_COLOR, /* ddjvu_render_mode_t */
    384                                     &rect,
    385                                     &rect,     /* mmc: ?? */
    386                                     format,
    387                                     stride, /* ?? */
    388                                     (char*)q);
    389         (void) ret;
    390         ddjvu_format_release(format);
    391 
    392 
    393         if (type == DDJVU_PAGETYPE_BITONAL) {
    394                 /*  */
    395 #if DEBUG
    396                 printf("%s: expanding BITONAL page/image\n", __FUNCTION__);
    397 #endif
    398                 size_t bit, byte;
    399 
    400                 for (y=0; y < (ssize_t) image->rows; y++)
    401                         {
    402                                 Quantum * o = QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    403                                 if (o == (Quantum *) NULL)
    404                                         break;
    405                                 bit=0;
    406                                 byte=0;
    407 
    408                                 /* fixme:  the non-aligned, last =<7 bits ! that's ok!!!*/
    409                                 for (x= 0; x < (ssize_t) image->columns; x++)
    410                                         {
    411                                                 if (bit == 0) byte= (size_t) q[(y * stride) + (x / 8)];
    412 
    413                                                 SetPixelIndex(image,(Quantum) (((byte & 0x01) != 0) ? 0x00 : 0x01),o);
    414                                                 bit++;
    415                                                 if (bit == 8)
    416                                                         bit=0;
    417                                                 byte>>=1;
    418                                           o+=GetPixelChannels(image);
    419                                         }
    420                                 if (SyncAuthenticPixels(image,exception) == MagickFalse)
    421                                         break;
    422                         }
    423                 if (!image->ping)
    424                   SyncImage(image,exception);
    425         } else {
    426 #if DEBUG
    427                 printf("%s: expanding PHOTO page/image\n", __FUNCTION__);
    428 #endif
    429                 /* now transfer line-wise: */
    430                 ssize_t i;
    431 #if 0
    432                 /* old: */
    433                 char* r;
    434 #else
    435                 register Quantum *r;
    436                 unsigned char *s;
    437 #endif
    438                 s=q;
    439                 for (i = 0;i< (ssize_t) image->rows; i++)
    440                         {
    441 #if DEBUG
    442                                if (i % 1000 == 0) printf("%d\n",i);
    443 #endif
    444                                r = QueueAuthenticPixels(image,0,i,image->columns,1,exception);
    445                                if (r == (Quantum *) NULL)
    446                                  break;
    447                   for (x=0; x < (ssize_t) image->columns; x++)
    448                   {
    449                     SetPixelRed(image,ScaleCharToQuantum(*s++),r);
    450                     SetPixelGreen(image,ScaleCharToQuantum(*s++),r);
    451                     SetPixelBlue(image,ScaleCharToQuantum(*s++),r);
    452                     r+=GetPixelChannels(image);
    453                   }
    454 
    455                               (void) SyncAuthenticPixels(image,exception);
    456                         }
    457         }
    458         q=(unsigned char *) RelinquishMagickMemory(q);
    459 }
    460 
    461 
    462 #if defined(MAGICKCORE_DJVU_DELEGATE)
    463 
    464 #if 0
    465 static int
    466 get_page_line(LoadContext *lc, int row, QuantumInfo* quantum_info)
    467 {
    468   ddjvu_format_t
    469     *format;
    470 
    471   int
    472     ret;
    473 
    474   size_t
    475     stride;
    476 
    477   unsigned char
    478     *q;
    479 
    480         ddjvu_rect_t rect, pagerect;
    481         rect.x = 0;
    482         rect.y = row;
    483         rect.w = lc->image->columns;             /* /10 */
    484         rect.h = 1;             /* /10 */
    485 
    486         pagerect.x = 0;
    487         pagerect.y = 0;
    488         pagerect.w = lc->image->columns;
    489         pagerect.h = lc->image->rows;
    490 
    491 
    492         format = ddjvu_format_create(
    493 #if RGB
    494                 DDJVU_FORMAT_RGB24
    495 #else
    496                 DDJVU_FORMAT_GREY8
    497 #endif
    498                 ,
    499                 0, NULL);
    500         ddjvu_format_set_row_order(format, 1);
    501         ddjvu_format_set_y_direction(format, 1);
    502 
    503         stride=1;
    504 #if RGB
    505         stride=3;
    506 #endif
    507         q = (unsigned char *) AcquireQuantumMemory(lc->image->columns,stride);
    508 
    509         ret = ddjvu_page_render(lc->page,
    510                                     DDJVU_RENDER_COLOR, /* ddjvu_render_mode_t */
    511                                     &pagerect,
    512                                     &rect,     /* mmc: ?? */
    513                                     format,
    514                                     pagerect.w * 3, /* ?? */
    515                                     (char*)q);
    516 
    517         ImportQuantumPixels(lc->image,
    518                             (CacheView *) NULL,
    519                             quantum_info,
    520 #if RGB
    521                             RGBQuantum
    522 #else
    523                             GrayQuantum
    524 #endif
    525                             ,q,&lc->image->exception);
    526         q=(unsigned char *) RelinquishMagickMemory(q);
    527         ddjvu_format_release(format);
    528         return ret;
    529 }
    530 #endif
    531 #endif
    532 
    533 /*
    534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    535 %                                                                             %
    536 %                                                                             %
    537 %                                                                             %
    538 %   R e a d O n e D J V U I m a g e                                           %
    539 %                                                                             %
    540 %                                                                             %
    541 %                                                                             %
    542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    543 %
    544 %  ReadOneDJVUImage() reads a Portable Network Graphics (DJVU) image file
    545 %  (minus the 8-byte signature)  and returns it.  It allocates the memory
    546 %  necessary for the new Image structure and returns a pointer to the new
    547 %  image.
    548 %
    549 %  The format of the ReadOneDJVUImage method is:
    550 %
    551 %      Image *ReadOneDJVUImage(MngInfo *mng_info, const ImageInfo *image_info,
    552 %         ExceptionInfo *exception)
    553 %
    554 %  A description of each parameter follows:
    555 %
    556 %    o mng_info: Specifies a pointer to a MngInfo structure.
    557 %
    558 %    o image_info: the image info.
    559 %
    560 %    o exception: return any errors or warnings in this structure.
    561 %
    562 */
    563 
    564 static Image *ReadOneDJVUImage(LoadContext* lc,const int pagenum,
    565   const ImageInfo *image_info,ExceptionInfo *exception)
    566 {
    567   ddjvu_page_type_t
    568      type;
    569 
    570   ddjvu_pageinfo_t info;
    571   ddjvu_message_t *message;
    572   Image *image;
    573   int logging;
    574   int tag;
    575   MagickBooleanType status;
    576 
    577         /* so, we know that the page is there! Get its dimension, and  */
    578 
    579         /* Read one DJVU image */
    580         image = lc->image;
    581 
    582         /* register Quantum *q; */
    583 
    584         logging=LogMagickEvent(CoderEvent,GetMagickModule(), "  enter ReadOneDJVUImage()");
    585         (void) logging;
    586 
    587 #if DEBUG
    588         printf("====  Loading the page %d\n", pagenum);
    589 #endif
    590         lc->page = ddjvu_page_create_by_pageno(lc->document, pagenum); /*  0? */
    591 
    592         /* pump data untill the page is ready for rendering. */
    593         tag=(-1);
    594         do {
    595                 while ((message = ddjvu_message_peek(lc->context)))
    596                         {
    597                                 tag=process_message(message);
    598                                 if (tag == 0) break;
    599                                 ddjvu_message_pop(lc->context);
    600                         }
    601                 /* fixme: maybe exit? */
    602                 /* if (lc->error) break; */
    603 
    604                 message = pump_data_until_message(lc,image);
    605                 if (message)
    606                         do {
    607                                 tag=process_message(message);
    608                                 if (tag == 0) break;
    609                                 ddjvu_message_pop(lc->context);
    610                         } while ((message = ddjvu_message_peek(lc->context)));
    611         } while (!ddjvu_page_decoding_done(lc->page));
    612 
    613         ddjvu_document_get_pageinfo(lc->document, pagenum, &info);
    614 
    615         image->resolution.x = (float) info.dpi;
    616         image->resolution.y =(float) info.dpi;
    617         if (image_info->density != (char *) NULL)
    618           {
    619             int
    620               flags;
    621 
    622             GeometryInfo
    623               geometry_info;
    624 
    625             /*
    626               Set rendering resolution.
    627             */
    628             flags=ParseGeometry(image_info->density,&geometry_info);
    629             image->resolution.x=geometry_info.rho;
    630             image->resolution.y=geometry_info.sigma;
    631             if ((flags & SigmaValue) == 0)
    632               image->resolution.y=image->resolution.x;
    633             info.width*=image->resolution.x/info.dpi;
    634             info.height*=image->resolution.y/info.dpi;
    635             info.dpi=(ssize_t) MagickMax(image->resolution.x,image->resolution.y);
    636           }
    637         type = ddjvu_page_get_type(lc->page);
    638 
    639         /* double -> float! */
    640         /* image->gamma = (float)ddjvu_page_get_gamma(lc->page); */
    641 
    642         /* mmc:  set  image->depth  */
    643         /* mmc:  This from the type */
    644 
    645         image->columns=(size_t) info.width;
    646         image->rows=(size_t) info.height;
    647 
    648         /* mmc: bitonal should be palettized, and compressed! */
    649         if (type == DDJVU_PAGETYPE_BITONAL){
    650                 image->colorspace = GRAYColorspace;
    651                 image->storage_class = PseudoClass;
    652                 image->depth =  8UL;    /* i only support that? */
    653                 image->colors= 2;
    654                 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
    655                   ThrowReaderException(ResourceLimitError,
    656                    "MemoryAllocationFailed");
    657         } else {
    658                 image->colorspace = RGBColorspace;
    659                 image->storage_class = DirectClass;
    660                 /* fixme:  MAGICKCORE_QUANTUM_DEPTH ?*/
    661                 image->depth =  8UL;    /* i only support that? */
    662 
    663                 image->alpha_trait = BlendPixelTrait;
    664                 /* is this useful? */
    665         }
    666         status=SetImageExtent(image,image->columns,image->rows,exception);
    667         if (status == MagickFalse)
    668           return(DestroyImageList(image));
    669 #if DEBUG
    670         printf("now filling %.20g x %.20g\n",(double) image->columns,(double)
    671           image->rows);
    672 #endif
    673 
    674 
    675 #if 1                           /* per_line */
    676 
    677         /* q = QueueAuthenticPixels(image,0,0,image->columns,image->rows); */
    678         get_page_image(lc, lc->page, 0, 0, info.width, info.height, exception);
    679 #else
    680         int i;
    681         for (i = 0;i< image->rows; i++)
    682                 {
    683                         printf("%d\n",i);
    684                         q = QueueAuthenticPixels(image,0,i,image->columns,1);
    685                         get_page_line(lc, i, quantum_info);
    686                         SyncAuthenticPixels(image);
    687                 }
    688 
    689 #endif /* per_line */
    690 
    691 
    692 #if DEBUG
    693         printf("END: finished filling %.20g x %.20g\n",(double) image->columns,
    694           (double) image->rows);
    695 #endif
    696 
    697         if (!image->ping)
    698           SyncImage(image,exception);
    699         /* mmc: ??? Convert PNM pixels to runlength-encoded MIFF packets. */
    700         /* image->colors =  */
    701 
    702         /* how is the line padding  / stride? */
    703 
    704         if (lc->page) {
    705                 ddjvu_page_release(lc->page);
    706                 lc->page = NULL;
    707         }
    708 
    709         /* image->page.y=mng_info->y_off[mng_info->object_id]; */
    710         if (tag == 0)
    711           image=DestroyImage(image);
    712         return image;
    713         /* end of reading one DJVU page/image */
    714 }
    715 
    716 #if 0
    717 /* palette */
    718   if (AcquireImageColormap(image,2,exception) == MagickFalse)
    719     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    720   /*
    721     Monochrome colormap.   mmc: this the default!
    722   */
    723   image->colormap[0].red=QuantumRange;
    724   image->colormap[0].green=QuantumRange;
    725   image->colormap[0].blue=QuantumRange;
    726   image->colormap[1].red=0;
    727   image->colormap[1].green=0;
    728   image->colormap[1].blue=0;
    729 #endif
    730 
    731 static void djvu_close_lc(LoadContext* lc)
    732 {
    733         if (lc->document)
    734                 ddjvu_document_release(lc->document);
    735         if (lc->context)
    736                 ddjvu_context_release(lc->context);
    737         if (lc->page)
    738                 ddjvu_page_release(lc->page);
    739         RelinquishMagickMemory(lc);
    740 }
    741 
    742 static Image *ReadDJVUImage(const ImageInfo *image_info,
    743   ExceptionInfo *exception)
    744 {
    745   const char
    746     *url;
    747 
    748   ddjvu_message_t
    749     *message;
    750 
    751   Image
    752     *image,
    753     *images;
    754 
    755   int
    756     logging,
    757     use_cache;
    758 
    759   LoadContext
    760     *lc;
    761 
    762   MagickBooleanType
    763     status;
    764 
    765   register ssize_t
    766     i;
    767 
    768   /*
    769    * Open image file.
    770    */
    771   assert(image_info != (const ImageInfo *) NULL);
    772   assert(image_info->signature == MagickCoreSignature);
    773 
    774 
    775   if (image_info->debug != MagickFalse)
    776     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename);
    777 
    778   assert(exception != (ExceptionInfo *) NULL);
    779   assert(exception->signature == MagickCoreSignature);
    780 
    781 
    782   logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter ReadDJVUImage()");
    783   (void) logging;
    784 
    785   image = AcquireImage(image_info,exception); /* mmc: ?? */
    786 
    787 
    788   lc = (LoadContext *) NULL;
    789   status = OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    790   if (status == MagickFalse)
    791     ThrowReaderException(FileOpenError,"UnableToOpenFile");
    792   /*
    793     Verify DJVU signature.
    794   */
    795 #if 0
    796   count = ReadBlob(image,8,(unsigned char *) magic_number);
    797 
    798   /* IsDJVU(const unsigned char *magick,const size_t length) */
    799   if (memcmp(magic_number,"AT&TFORM",8) != 0)
    800     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    801 #endif
    802 
    803 
    804   /*
    805    * Allocate a LoadContext structure.
    806    */
    807   lc = (LoadContext *) AcquireMagickMemory(sizeof(*lc));
    808   if (lc == NULL)
    809     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    810 
    811 
    812   /*
    813    * Initialize members of the MngInfo structure.
    814    */
    815   (void) ResetMagickMemory(lc,0,sizeof(LoadContext));
    816 
    817   lc->image = image;
    818   lc->pages = 0;
    819   lc->context = ddjvu_context_create("ImageMagick djvu loader"); /* g_program_name */
    820 
    821   ddjvu_cache_set_size(lc->context, 1); /* right? */
    822   use_cache = 0;
    823   /* document: here we don't have a filename, but, for the sake of generality, a FILE* ! */
    824   url="http://www.imagemagick.org/fake.djvu";
    825   lc->document = ddjvu_document_create(lc->context, url, use_cache); /* don't cache */
    826   ddjvu_document_set_user_data(lc->document, lc);
    827 
    828 
    829   /* now we wait the message-request for data: */
    830   message = ddjvu_message_wait(lc->context);
    831 
    832   if (message->m_any.tag != DDJVU_NEWSTREAM) {
    833           /* fixme: the djvu context, document! */
    834 
    835           ddjvu_document_release(lc->document);
    836           ddjvu_context_release(lc->context);
    837 
    838           RelinquishMagickMemory(lc);
    839 
    840           ThrowReaderException(ResourceLimitError,"Djvu initial message: unexpected type");
    841           return NULL;    /* error! */
    842   };
    843 
    844   lc->streamid = message->m_newstream.streamid;
    845   ddjvu_message_pop(lc->context);
    846 
    847   message = pump_data_until_message(lc,image);
    848   /* now process the messages: */
    849 
    850 
    851   if (message) do {
    852           process_message(message);
    853           ddjvu_message_pop(lc->context);
    854   } while ((message = ddjvu_message_peek(lc->context)));
    855 
    856   /* fixme: i hope we have not read any messages pertinent(?) related to the page itself!  */
    857 
    858   while (lc->pages == 0) {
    859           message = ddjvu_message_wait(lc->context);
    860           process_message(message);
    861           ddjvu_message_pop(lc->context);
    862   }
    863 
    864   images=NewImageList();
    865   i=0;
    866   if (image_info->number_scenes != 0)
    867     i=image_info->scene;
    868   for ( ; i < (ssize_t) lc->pages; i++)
    869   {
    870     image=ReadOneDJVUImage(lc,i,image_info,exception);
    871     if (image == (Image *) NULL)
    872       break;
    873     image->scene=i;
    874     AppendImageToList(&images,CloneImageList(image,exception));
    875     images->extent=GetBlobSize(image);
    876     if (image_info->number_scenes != 0)
    877       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    878         break;
    879   }
    880   djvu_close_lc(lc);
    881   (void) CloseBlob(images);
    882   if (image != (Image *) NULL)
    883     image=DestroyImageList(image);
    884 
    885 #if 0
    886   if ((image->page.width == 0) && (image->page.height == 0))
    887     {
    888       image->page.width = image->columns+image->page.x;
    889       image->page.height = image->rows+image->page.y;
    890     }
    891   if (image->columns == 0 || image->rows == 0)
    892     {
    893       if (logging != MagickFalse)
    894         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    895           "exit ReadDJVUImage() with error.");
    896       ThrowReaderException(CorruptImageError,"CorruptImage");
    897     }
    898 
    899   if (logging != MagickFalse)
    900     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadDJVUImage()");
    901 #endif
    902 
    903 
    904   return(GetFirstImageInList(images));
    905 }
    906 #endif
    907 
    908 /*
    910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    911 %                                                                             %
    912 %                                                                             %
    913 %                                                                             %
    914 %   R e g i s t e r D J V U I m a g e                                         %
    915 %                                                                             %
    916 %                                                                             %
    917 %                                                                             %
    918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    919 %
    920 %  RegisterDJVUImage() adds attributes for the DJVU image format to
    921 %  the list of supported formats.  The attributes include the image format
    922 %  tag, a method to read and/or write the format, whether the format
    923 %  supports the saving of more than one frame to the same file or blob,
    924 %  whether the format supports native in-memory I/O, and a brief
    925 %  description of the format.
    926 %
    927 %  The format of the RegisterDJVUImage method is:
    928 %
    929 %      size_t RegisterDJVUImage(void)
    930 %
    931 */
    932 ModuleExport size_t RegisterDJVUImage(void)
    933 {
    934   char
    935     version[MagickPathExtent];
    936 
    937   MagickInfo
    938     *entry;
    939 
    940   static const char
    941     *DJVUNote =
    942     {
    943       "See http://www.djvuzone.org/ for details about the DJVU format.  The\n"
    944       "DJVU 1.2 specification is available there and at\n"
    945       "ftp://swrinde.nde.swri.edu/pub/djvu/documents/."
    946     };
    947 
    948   *version='\0';
    949 #if defined(DJVU_LIBDJVU_VER_STRING)
    950   (void) ConcatenateMagickString(version,"libdjvu ",MagickPathExtent);
    951   (void) ConcatenateMagickString(version,DJVU_LIBDJVU_VER_STRING,MagickPathExtent);
    952 #endif
    953   entry=AcquireMagickInfo("DJVU","DJVU","Deja vu");
    954 #if defined(MAGICKCORE_DJVU_DELEGATE)
    955   entry->decoder=(DecodeImageHandler *) ReadDJVUImage;
    956 #endif
    957   entry->magick=(IsImageFormatHandler *) IsDJVU;
    958   entry->flags|=CoderRawSupportFlag;
    959   entry->flags^=CoderAdjoinFlag;
    960   if (*version != '\0')
    961     entry->version=AcquireString(version);
    962   entry->note=AcquireString(DJVUNote);
    963   (void) RegisterMagickInfo(entry);
    964   return(MagickImageCoderSignature);
    965 }
    966 
    967 /*
    969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    970 %                                                                             %
    971 %                                                                             %
    972 %                                                                             %
    973 %   U n r e g i s t e r D J V U I m a g e                                     %
    974 %                                                                             %
    975 %                                                                             %
    976 %                                                                             %
    977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    978 %
    979 %  UnregisterDJVUImage() removes format registrations made by the
    980 %  DJVU module from the list of supported formats.
    981 %
    982 %  The format of the UnregisterDJVUImage method is:
    983 %
    984 %      UnregisterDJVUImage(void)
    985 %
    986 */
    987 ModuleExport void UnregisterDJVUImage(void)
    988 {
    989   (void) UnregisterMagickInfo("DJVU");
    990 }
    991