-
Notifications
You must be signed in to change notification settings - Fork 32
/
djvulibre.c
117 lines (109 loc) · 2.6 KB
/
djvulibre.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libdjvu/ddjvuapi.h>
#include "draw.h"
#include "doc.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
struct doc {
ddjvu_context_t *ctx;
ddjvu_document_t *doc;
};
int djvu_handle(struct doc *doc)
{
ddjvu_message_t *msg;
msg = ddjvu_message_wait(doc->ctx);
while ((msg = ddjvu_message_peek(doc->ctx))) {
if (msg->m_any.tag == DDJVU_ERROR) {
fprintf(stderr,"ddjvu: %s\n", msg->m_error.message);
return 1;
}
ddjvu_message_pop(doc->ctx);
}
return 0;
}
static void djvu_render(ddjvu_page_t *page, int iw, int ih, void *bitmap)
{
ddjvu_format_t *fmt;
ddjvu_rect_t rect;
rect.x = 0;
rect.y = 0;
rect.w = iw;
rect.h = ih;
fmt = ddjvu_format_create(DDJVU_FORMAT_RGB24, 0, 0);
ddjvu_format_set_row_order(fmt, 1);
memset(bitmap, 0, ih * iw * 3);
ddjvu_page_render(page, DDJVU_RENDER_COLOR,
&rect, &rect, fmt, iw * 3, bitmap);
ddjvu_format_release(fmt);
}
void *doc_draw(struct doc *doc, int p, int zoom, int rotate, int *rows, int *cols)
{
ddjvu_page_t *page;
ddjvu_pageinfo_t info;
int iw, ih, dpi;
unsigned char *bmp;
fbval_t *pbuf;
int i, j;
page = ddjvu_page_create_by_pageno(doc->doc, p - 1);
if (!page)
return NULL;
while (!ddjvu_page_decoding_done(page))
if (djvu_handle(doc))
return NULL;
if (rotate)
ddjvu_page_set_rotation(page, (4 - (rotate / 90 % 4)) & 3);
ddjvu_document_get_pageinfo(doc->doc, p - 1, &info);
dpi = ddjvu_page_get_resolution(page);
iw = ddjvu_page_get_width(page) * zoom / dpi;
ih = ddjvu_page_get_height(page) * zoom / dpi;
if (!(bmp = malloc(ih * iw * 3))) {
ddjvu_page_release(page);
return NULL;
}
djvu_render(page, iw, ih, bmp);
ddjvu_page_release(page);
if (!(pbuf = malloc(ih * iw * sizeof(pbuf[0])))) {
free(bmp);
return NULL;
}
for (i = 0; i < ih; i++) {
unsigned char *src = bmp + i * iw * 3;
fbval_t *dst = pbuf + i * iw;
for (j = 0; j < iw; j++)
dst[j] = FB_VAL(src[j * 3], src[j * 3 + 1], src[j * 3 + 2]);
}
free(bmp);
*cols = iw;
*rows = ih;
return pbuf;
}
int doc_pages(struct doc *doc)
{
return ddjvu_document_get_pagenum(doc->doc);
}
struct doc *doc_open(char *path)
{
struct doc *doc = malloc(sizeof(*doc));
doc->ctx = ddjvu_context_create("fbpdf");
if (!doc->ctx)
goto fail;
doc->doc = ddjvu_document_create_by_filename(doc->ctx, path, 1);
if (!doc->doc)
goto fail;
while (!ddjvu_document_decoding_done(doc->doc))
if (djvu_handle(doc))
goto fail;
return doc;
fail:
doc_close(doc);
return NULL;
}
void doc_close(struct doc *doc)
{
if (doc->doc)
ddjvu_context_release(doc->ctx);
if (doc->ctx)
ddjvu_document_release(doc->doc);
free(doc);
}