/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % DDDD J V V U U % % D D J V V U U % % D D J V V U U % % D D J J V V U U % % DDDD JJJ V UUU % % % % % % Read DjVu Images. % % % % Software Design % % Cristy % % July 1992 % % % % % % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization % % dedicated to making software imaging solutions freely available. % % % % You may not use this file except in compliance with the License. You may % % obtain a copy of the License at % % % % https://imagemagick.org/script/license.php % % % % Unless required by applicable law or agreed to in writing, software % % distributed under the License is distributed on an "AS IS" BASIS, % % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % % See the License for the specific language governing permissions and % % limitations under the License. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % */ /* Include declarations. */ #include "MagickCore/studio.h" #include "MagickCore/blob.h" #include "MagickCore/blob-private.h" #include "MagickCore/cache.h" #include "MagickCore/colormap.h" #include "MagickCore/constitute.h" #include "MagickCore/exception.h" #include "MagickCore/exception-private.h" #include "MagickCore/image-private.h" #include "MagickCore/list.h" #include "MagickCore/magick.h" #include "MagickCore/memory_.h" #include "MagickCore/monitor.h" #include "MagickCore/monitor-private.h" #include "MagickCore/pixel-accessor.h" #include "MagickCore/quantum-private.h" #include "MagickCore/static.h" #include "MagickCore/string_.h" #include "MagickCore/module.h" #if defined(MAGICKCORE_DJVU_DELEGATE) #include #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I s D J V U % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % IsDJVU() returns MagickTrue if the image format type, identified by the % magick string, is DJVU. % % The format of the IsDJVU method is: % % MagickBooleanType IsDJVU(const unsigned char *magick,const size_t length) % % A description of each parameter follows: % % o magick: compare image format pattern against these bytes. % % o length: Specifies the length of the magick string. % */ static MagickBooleanType IsDJVU(const unsigned char *magick,const size_t length) { if (length < 8) return(MagickFalse); if (memcmp(magick,"AT&TFORM",8) == 0) return(MagickTrue); return(MagickFalse); } #if defined(MAGICKCORE_DJVU_DELEGATE) /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D J V U I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadDJVUImage() reads DJVU image and returns it. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image or set of images. % % The format of the ReadDJVUImage method is: % % Image *ReadDJVUImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct _LoadContext LoadContext; struct _LoadContext { ddjvu_context_t* context; ddjvu_document_t *document; ddjvu_page_t *page; int streamid; int pages; Image *image; }; #define BLOCKSIZE 65536 #if 0 static void pump_data(Image *image, LoadContext* lc) { int blocksize = BLOCKSIZE; char data[BLOCKSIZE]; int size; /* i might check for a condition! */ while ((size = (size_t) ReadBlob(image,(size_t) blocksize,data)) == blocksize) { ddjvu_stream_write(lc->document, lc->streamid, data, size); } if (size) ddjvu_stream_write(lc->document, lc->streamid, data, size); ddjvu_stream_close(lc->document, lc->streamid, 0); } #endif /* returns NULL only after all is delivered! */ static ddjvu_message_t* pump_data_until_message(LoadContext *lc,Image *image) /* ddjvu_context_t *context, type ddjvu_document_type_t */ { size_t blocksize = BLOCKSIZE; unsigned char data[BLOCKSIZE]; size_t size; ddjvu_message_t *message; /* i might check for a condition! */ size=0; while (!(message = ddjvu_message_peek(lc->context)) && (size = (size_t) ReadBlob(image,(size_t) blocksize,data)) == blocksize) { ddjvu_stream_write(lc->document, lc->streamid, (char *) data, size); } if (message) return message; if (size) ddjvu_stream_write(lc->document, lc->streamid, (char *) data, size); ddjvu_stream_close(lc->document, lc->streamid, 0); return NULL; } #define DEBUG 0 #if DEBUG static const char *message_tag_name(ddjvu_message_tag_t tag) { static char* names[] = { "ERROR", "INFO", "NEWSTREAM", "DOCINFO", "PAGEINFO", "RELAYOUT", "REDISPLAY", "CHUNK", "THUMBNAIL", "PROGRESS", }; if (tag <= DDJVU_PROGRESS) return names[tag]; else { /* bark! */ return 0; } } #endif /* write out nice info on the message, * and store in *user* data the info on progress. * */ int process_message(ddjvu_message_t *message) { #if 0 ddjvu_context_t* context= message->m_any.context; #endif if (! message) return(-1); #if DEBUG printf("*** %s: %s.\n",__FUNCTION__, message_tag_name(message->m_any.tag)); #endif switch (message->m_any.tag){ case DDJVU_DOCINFO: { ddjvu_document_t* document= message->m_any.document; /* ddjvu_document_decoding_status is set by libdjvu! */ /* we have some info on the document */ LoadContext *lc = (LoadContext *) ddjvu_document_get_user_data(document); lc->pages = ddjvu_document_get_pagenum(document); #if DEBUG printf("the doc has %d pages\n", ddjvu_document_get_pagenum(document)); #endif break; } case DDJVU_CHUNK: #if DEBUG printf("the name of the chunk is: %s\n", message->m_chunk.chunkid); #endif break; case DDJVU_RELAYOUT: case DDJVU_PAGEINFO: { #if 0 ddjvu_page_t* page = message->m_any.page; page_info* info = ddjvu_page_get_user_data(page); printf("page decoding status: %d %s%s%s\n", ddjvu_page_decoding_status(page), status_color, status_name(ddjvu_page_decoding_status(page)), color_reset); printf("the page LAYOUT changed: width x height: %d x %d @ %d dpi. Version %d, type %d\n", // printf("page info:\n width x height: %d x %d @ %d dpi, version %d, type %d\n", ddjvu_page_get_width(page), ddjvu_page_get_height(page), ddjvu_page_get_resolution(page), ddjvu_page_get_version(page), /* DDJVU_PAGETYPE_BITONAL */ ddjvu_page_get_type(page)); info->info = 1; #endif break; } case DDJVU_REDISPLAY: { #if 0 ddjvu_page_t* page = message->m_any.page; page_info* info = ddjvu_page_get_user_data(page); printf("the page can/should be REDISPLAYED\n"); info->display = 1; #endif break; } case DDJVU_PROGRESS: #if DEBUG printf("PROGRESS:\n"); #endif break; case DDJVU_ERROR: printf("simply ERROR!\n message:\t%s\nfunction:\t%s(file %s)\nlineno:\t%d\n", message->m_error.message, message->m_error.function, message->m_error.filename, message->m_error.lineno); break; case DDJVU_INFO: #if DEBUG printf("INFO: %s!\n", message->m_info.message); #endif break; default: printf("unexpected\n"); }; return(message->m_any.tag); } #if defined(__cplusplus) || defined(c_plusplus) } #endif #define RGB 1 /* * DjVu advertised readiness to provide bitmap: So get it! * we use the RGB format! */ static void get_page_image(LoadContext *lc, ddjvu_page_t *page, int x, int y, int w, int h, ExceptionInfo *exception ) { ddjvu_format_t *format; ddjvu_page_type_t type; Image *image; int ret, stride; unsigned char *q; ddjvu_rect_t rect; rect.x = x; rect.y = y; rect.w = (unsigned int) w; /* /10 */ rect.h = (unsigned int) h; /* /10 */ image = lc->image; type = ddjvu_page_get_type(lc->page); /* stride of this temporary buffer: */ stride = (type == DDJVU_PAGETYPE_BITONAL)? (image->columns + 7)/8 : image->columns *3; q = (unsigned char *) AcquireQuantumMemory(image->rows,stride); if (q == (unsigned char *) NULL) return; format = ddjvu_format_create( (type == DDJVU_PAGETYPE_BITONAL)?DDJVU_FORMAT_LSBTOMSB : DDJVU_FORMAT_RGB24, /* DDJVU_FORMAT_RGB24 * DDJVU_FORMAT_RGBMASK32*/ /* DDJVU_FORMAT_RGBMASK32 */ 0, NULL); #if 0 /* fixme: ThrowReaderException is a macro, which uses `exception' variable */ if (format == NULL) { abort(); /* ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); */ } #endif ddjvu_format_set_row_order(format, 1); ddjvu_format_set_y_direction(format, 1); ret = ddjvu_page_render(page, DDJVU_RENDER_COLOR, /* ddjvu_render_mode_t */ &rect, &rect, /* mmc: ?? */ format, stride, /* ?? */ (char*)q); (void) ret; ddjvu_format_release(format); if (type == DDJVU_PAGETYPE_BITONAL) { /* */ #if DEBUG printf("%s: expanding BITONAL page/image\n", __FUNCTION__); #endif size_t bit, byte; for (y=0; y < (ssize_t) image->rows; y++) { Quantum * o = QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (o == (Quantum *) NULL) break; bit=0; byte=0; /* fixme: the non-aligned, last =<7 bits ! that's ok!!!*/ for (x= 0; x < (ssize_t) image->columns; x++) { if (bit == 0) byte= (size_t) q[(y * stride) + (x / 8)]; SetPixelIndex(image,(Quantum) (((byte & 0x01) != 0) ? 0x00 : 0x01),o); bit++; if (bit == 8) bit=0; byte>>=1; o+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } if (!image->ping) SyncImage(image,exception); } else { #if DEBUG printf("%s: expanding PHOTO page/image\n", __FUNCTION__); #endif /* now transfer line-wise: */ ssize_t i; #if 0 /* old: */ char* r; #else Quantum *r; unsigned char *s; #endif s=q; for (i = 0;i< (ssize_t) image->rows; i++) { #if DEBUG if (i % 1000 == 0) printf("%d\n",i); #endif r = QueueAuthenticPixels(image,0,i,image->columns,1,exception); if (r == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(image,ScaleCharToQuantum(*s++),r); SetPixelGreen(image,ScaleCharToQuantum(*s++),r); SetPixelBlue(image,ScaleCharToQuantum(*s++),r); r+=GetPixelChannels(image); } (void) SyncAuthenticPixels(image,exception); } } q=(unsigned char *) RelinquishMagickMemory(q); } #if defined(MAGICKCORE_DJVU_DELEGATE) #if 0 static int get_page_line(LoadContext *lc, int row, QuantumInfo* quantum_info) { ddjvu_format_t *format; int ret; size_t stride; unsigned char *q; ddjvu_rect_t rect, pagerect; rect.x = 0; rect.y = row; rect.w = lc->image->columns; /* /10 */ rect.h = 1; /* /10 */ pagerect.x = 0; pagerect.y = 0; pagerect.w = lc->image->columns; pagerect.h = lc->image->rows; format = ddjvu_format_create( #if RGB DDJVU_FORMAT_RGB24 #else DDJVU_FORMAT_GREY8 #endif , 0, NULL); ddjvu_format_set_row_order(format, 1); ddjvu_format_set_y_direction(format, 1); stride=1; #if RGB stride=3; #endif q = (unsigned char *) AcquireQuantumMemory(lc->image->columns,stride); ret = ddjvu_page_render(lc->page, DDJVU_RENDER_COLOR, /* ddjvu_render_mode_t */ &pagerect, &rect, /* mmc: ?? */ format, pagerect.w * 3, /* ?? */ (char*)q); ImportQuantumPixels(lc->image, (CacheView *) NULL, quantum_info, #if RGB RGBQuantum #else GrayQuantum #endif ,q,&lc->image->exception); q=(unsigned char *) RelinquishMagickMemory(q); ddjvu_format_release(format); return ret; } #endif #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d O n e D J V U I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadOneDJVUImage() reads a Portable Network Graphics (DJVU) image file % (minus the 8-byte signature) and returns it. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image. % % The format of the ReadOneDJVUImage method is: % % Image *ReadOneDJVUImage(MngInfo *mng_info, const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o mng_info: Specifies a pointer to a MngInfo structure. % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadOneDJVUImage(LoadContext* lc,const int pagenum, const ImageInfo *image_info,ExceptionInfo *exception) { ddjvu_page_type_t type; ddjvu_pageinfo_t info; ddjvu_message_t *message; Image *image; int logging; int tag; MagickBooleanType status; /* so, we know that the page is there! Get its dimension, and */ /* Read one DJVU image */ image = lc->image; /* Quantum *q; */ logging=LogMagickEvent(CoderEvent,GetMagickModule(), " enter ReadOneDJVUImage()"); (void) logging; #if DEBUG printf("==== Loading the page %d\n", pagenum); #endif lc->page = ddjvu_page_create_by_pageno(lc->document, pagenum); /* 0? */ /* pump data untill the page is ready for rendering. */ tag=(-1); do { while ((message = ddjvu_message_peek(lc->context))) { tag=process_message(message); if (tag == 0) break; ddjvu_message_pop(lc->context); } /* fixme: maybe exit? */ /* if (lc->error) break; */ message = pump_data_until_message(lc,image); if (message) do { tag=process_message(message); if (tag == 0) break; ddjvu_message_pop(lc->context); } while ((message = ddjvu_message_peek(lc->context))); if (tag == 0) break; } while (!ddjvu_page_decoding_done(lc->page)); ddjvu_document_get_pageinfo(lc->document, pagenum, &info); image->resolution.x = (float) info.dpi; image->resolution.y =(float) info.dpi; if (image_info->density != (char *) NULL) { int flags; GeometryInfo geometry_info; /* Set rendering resolution. */ flags=ParseGeometry(image_info->density,&geometry_info); image->resolution.x=geometry_info.rho; image->resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) image->resolution.y=image->resolution.x; info.width*=image->resolution.x/info.dpi; info.height*=image->resolution.y/info.dpi; info.dpi=(ssize_t) MagickMax(image->resolution.x,image->resolution.y); } type = ddjvu_page_get_type(lc->page); /* double -> float! */ /* image->gamma = (float)ddjvu_page_get_gamma(lc->page); */ /* mmc: set image->depth */ /* mmc: This from the type */ image->columns=(size_t) info.width; image->rows=(size_t) info.height; /* mmc: bitonal should be palettized, and compressed! */ if (type == DDJVU_PAGETYPE_BITONAL){ image->colorspace = GRAYColorspace; image->storage_class = PseudoClass; image->depth = 8UL; /* i only support that? */ image->colors= 2; if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) ThrowReaderException(ResourceLimitError, "MemoryAllocationFailed"); } else { image->colorspace = RGBColorspace; image->storage_class = DirectClass; /* fixme: MAGICKCORE_QUANTUM_DEPTH ?*/ image->depth = 8UL; /* i only support that? */ image->alpha_trait = BlendPixelTrait; /* is this useful? */ } status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); #if DEBUG printf("now filling %.20g x %.20g\n",(double) image->columns,(double) image->rows); #endif #if 1 /* per_line */ /* q = QueueAuthenticPixels(image,0,0,image->columns,image->rows); */ get_page_image(lc, lc->page, 0, 0, info.width, info.height, exception); #else int i; for (i = 0;i< image->rows; i++) { printf("%d\n",i); q = QueueAuthenticPixels(image,0,i,image->columns,1); get_page_line(lc, i, quantum_info); SyncAuthenticPixels(image); } #endif /* per_line */ #if DEBUG printf("END: finished filling %.20g x %.20g\n",(double) image->columns, (double) image->rows); #endif if (!image->ping) SyncImage(image,exception); /* mmc: ??? Convert PNM pixels to runlength-encoded MIFF packets. */ /* image->colors = */ /* how is the line padding / stride? */ if (lc->page) { ddjvu_page_release(lc->page); lc->page = NULL; } /* image->page.y=mng_info->y_off[mng_info->object_id]; */ if (tag == 0) image=DestroyImage(image); return image; /* end of reading one DJVU page/image */ } #if 0 /* palette */ if (AcquireImageColormap(image,2,exception) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); /* Monochrome colormap. mmc: this the default! */ image->colormap[0].red=QuantumRange; image->colormap[0].green=QuantumRange; image->colormap[0].blue=QuantumRange; image->colormap[1].red=0; image->colormap[1].green=0; image->colormap[1].blue=0; #endif static void djvu_close_lc(LoadContext* lc) { if (lc->document) ddjvu_document_release(lc->document); if (lc->context) ddjvu_context_release(lc->context); if (lc->page) ddjvu_page_release(lc->page); RelinquishMagickMemory(lc); } static Image *ReadDJVUImage(const ImageInfo *image_info, ExceptionInfo *exception) { const char *url; ddjvu_message_t *message; Image *image, *images; int logging, use_cache; LoadContext *lc; MagickBooleanType status; ssize_t i; /* * Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter ReadDJVUImage()"); (void) logging; image = AcquireImage(image_info,exception); /* mmc: ?? */ lc = (LoadContext *) NULL; status = OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) ThrowReaderException(FileOpenError,"UnableToOpenFile"); /* Verify DJVU signature. */ #if 0 count = ReadBlob(image,8,(unsigned char *) magic_number); /* IsDJVU(const unsigned char *magick,const size_t length) */ if (memcmp(magic_number,"AT&TFORM",8) != 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); #endif /* * Allocate a LoadContext structure. */ lc = (LoadContext *) AcquireMagickMemory(sizeof(*lc)); if (lc == NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); /* * Initialize members of the MngInfo structure. */ (void) memset(lc,0,sizeof(LoadContext)); lc->image = image; lc->pages = 0; lc->context = ddjvu_context_create("ImageMagick djvu loader"); /* g_program_name */ ddjvu_cache_set_size(lc->context, 1); /* right? */ use_cache = 0; /* document: here we don't have a filename, but, for the sake of generality, a FILE* ! */ url="https://imagemagick.org/fake.djvu"; lc->document = ddjvu_document_create(lc->context, url, use_cache); /* don't cache */ ddjvu_document_set_user_data(lc->document, lc); /* now we wait the message-request for data: */ message = ddjvu_message_wait(lc->context); if (message->m_any.tag != DDJVU_NEWSTREAM) { /* fixme: the djvu context, document! */ ddjvu_document_release(lc->document); ddjvu_context_release(lc->context); RelinquishMagickMemory(lc); ThrowReaderException(ResourceLimitError,"Djvu initial message: unexpected type"); return NULL; /* error! */ }; lc->streamid = message->m_newstream.streamid; ddjvu_message_pop(lc->context); message = pump_data_until_message(lc,image); /* now process the messages: */ if (message) do { process_message(message); ddjvu_message_pop(lc->context); } while ((message = ddjvu_message_peek(lc->context))); /* fixme: i hope we have not read any messages pertinent(?) related to the page itself! */ while (lc->pages == 0) { message = ddjvu_message_wait(lc->context); process_message(message); ddjvu_message_pop(lc->context); } images=NewImageList(); i=0; if (image_info->number_scenes != 0) i=image_info->scene; for ( ; i < (ssize_t) lc->pages; i++) { image=ReadOneDJVUImage(lc,i,image_info,exception); if (image == (Image *) NULL) break; image->scene=i; AppendImageToList(&images,CloneImageList(image,exception)); images->extent=GetBlobSize(image); if (image_info->number_scenes != 0) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; } djvu_close_lc(lc); if (images != (Image *) NULL) (void) CloseBlob(images); if (image != (Image *) NULL) image=DestroyImageList(image); #if 0 if ((image->page.width == 0) && (image->page.height == 0)) { image->page.width = image->columns+image->page.x; image->page.height = image->rows+image->page.y; } if (image->columns == 0 || image->rows == 0) { if (logging != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "exit ReadDJVUImage() with error."); ThrowReaderException(CorruptImageError,"CorruptImage"); } if (logging != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadDJVUImage()"); #endif return(GetFirstImageInList(images)); } #endif /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e g i s t e r D J V U I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RegisterDJVUImage() adds attributes for the DJVU image format to % the list of supported formats. The attributes include the image format % tag, a method to read and/or write the format, whether the format % supports the saving of more than one frame to the same file or blob, % whether the format supports native in-memory I/O, and a brief % description of the format. % % The format of the RegisterDJVUImage method is: % % size_t RegisterDJVUImage(void) % */ ModuleExport size_t RegisterDJVUImage(void) { char version[MagickPathExtent]; MagickInfo *entry; static const char *DJVUNote = { "See http://www.djvuzone.org/ for details about the DJVU format. The\n" "DJVU 1.2 specification is available there and at\n" "ftp://swrinde.nde.swri.edu/pub/djvu/documents/." }; *version='\0'; #if defined(DJVU_LIBDJVU_VER_STRING) (void) ConcatenateMagickString(version,"libdjvu ",MagickPathExtent); (void) ConcatenateMagickString(version,DJVU_LIBDJVU_VER_STRING,MagickPathExtent); #endif entry=AcquireMagickInfo("DJVU","DJVU","Deja vu"); #if defined(MAGICKCORE_DJVU_DELEGATE) entry->decoder=(DecodeImageHandler *) ReadDJVUImage; #endif entry->magick=(IsImageFormatHandler *) IsDJVU; entry->flags|=CoderRawSupportFlag; entry->flags^=CoderAdjoinFlag; if (*version != '\0') entry->version=AcquireString(version); entry->note=AcquireString(DJVUNote); (void) RegisterMagickInfo(entry); return(MagickImageCoderSignature); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % U n r e g i s t e r D J V U I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % UnregisterDJVUImage() removes format registrations made by the % DJVU module from the list of supported formats. % % The format of the UnregisterDJVUImage method is: % % UnregisterDJVUImage(void) % */ ModuleExport void UnregisterDJVUImage(void) { (void) UnregisterMagickInfo("DJVU"); }