You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

987 lines
32 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 <libdjvu/ddjvuapi.h>
#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");
}