#include "djv_document.h" // for Document class #include "djv_page.h" // for Page class #include "djv_serialize.h" // for IFF::serialize, \ref IFF::deserialize using namespace Celartem; using namespace Celartem::DjVu;
Since the base library is shared with PixelLive SDK, they're in Celartem namespace while DjVu related classes are in Celartem::DjVu namespace.
AutoPtr<Storage> storage = Storage::create("myfirst.djvu");
AutoPtr<DiskStorage> storage = Storage::create("http://sample.celartem.com/images/mrsaito.djvu");
AutoPtr<Document> doc = Document::create(storage);
But you can also use the following easier way, which does not require you to open Storage instance separately:
AutoPtr<Document> doc = Document::create("http://sample.celartem.com/images/mrsaito.djvu");
AutoPtr<Page> page = doc->getPages()[0];
You can also know how much pages in the Document by the following code:
size_t pageCount = doc->getPages().getSize();
// get the "pixel" size of the page size_t w = page->getWidth(); size_t h = page->getHeight();
The code above can get the "pixel" size of the page but it's very large to show all the portion in a display. So we should calculate the size which is fit into the display. In this tutorial, I'll introduce a way to get physical size from the page's resolution, known as dot-per-inch.
// here we assume the display is 96dpi. size_t dw = w * 96 / page->getDpi(); size_t dh = h * 96 / page->getDpi();
OK, now render the pixel image:
size_t stride = dw * 3; // bytes-per-line; a R-G-B pixel consumes 3 bytes size_t byteSize = stride * dh; // Firstly allocate memory, which stores the rendered output. // Since we don't plan to resize the buffer, make the size and the reservation // size same; the second parameter is the reserved size. SimpleArray<u8> buffer(byteSize, byteSize); page->render( &buffer[0], stride, pmRGB8, Rect(0, 0, dw, dh), // left, top, width, height of the portion to render dw, dh);
The 5th,6th parameter of Page::render method specifies the rendering image size in pixels and the 4th paramether specifies which portion of the image is actually stored to the buffer; actual picture size rendered is controled by the 4th parameter.
AutoPtr<Chunk> chunk = page->getChunk();
And basically, Document instance is the actual owner of page chunks. So you can also access chunks from Document instance:
AutoPtr<Chunk> djvmChunk = doc->getChunk();
Chunk::Array& chunks = djvmChunk->getChildren(); size_t count = chunks.getSize(); for(size_t i = 0; i < count; i++) { AutoPtr<Chunk> chunk = chunks[i]; ... }
if(djvmChunk->isCollection()) { // yeah, DJVM is really a chunk which contains child chunks! } else { // it seems it does not have any children. }
AutoPtr<Storage> storage = Storage::create("myfirst.djvu"); AutoPtr<Chunk> chunk = IFF::deserialize(storage);
AutoPtr<DiskStorageWithRollback> storageW = DiskStorageWithRollback::create("saved.djvu", accessWrite); IFF::serialize(storageW, chunk); storageW->commit();
Of course, Document class provides a way to save the Document:
AutoPtr<DiskStorageWithRollback> storageW = DiskStorageWithRollback::create("saved.djvu", accessWrite); doc->save(storageW); storageW->commit();
AutoPtr<DiskStorageWithRollback> storageW = DiskStorageWithRollback::create("saved.djvu", accessWrite); IFF::serialize(storageW, doc->getChunk()); storageW->commit();
When you modify Document instance, you have to synchronize the chunk before directly access it:
doSomeModificationOnDocument(doc); doc->updateChunks(); // reflect to the chunks IFF::serialize(storageW, doc->getChunk());
In the same way, when you modify some part of the chunk which is obtained from Document instance, you should synchronize the Document instance before using Document::save method:
doSomeModificationOnChunk(doc->getChunk()); doc->syncToChunks(); doc->save(...);