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