MuseScore/omr/pdf.cpp
2013-05-21 09:44:49 +02:00

163 lines
4.6 KiB
C++

//=============================================================================
// MusE Reader
// Music Score Reader
// $Id$
//
// Copyright (C) 2010 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "pdf.h"
extern "C" {
#include <fitz.h>
// #include <mupdf.h>
}
namespace Ms {
int Pdf::references;
static fz_context* ctx;
//---------------------------------------------------------
// numPages
//---------------------------------------------------------
int Pdf::numPages() const
{
return fz_count_pages(doc);
}
//---------------------------------------------------------
// Pdf
//---------------------------------------------------------
Pdf::Pdf()
{
if (references == 0)
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); // 256MB cache
++references;
doc = 0;
}
//---------------------------------------------------------
// open
//---------------------------------------------------------
bool Pdf::open(const QString& path)
{
char* name = path.toLatin1().data();
fz_try(ctx) {
doc = fz_open_document(ctx, name);
}
fz_catch(ctx) {
fz_close_document(doc);
doc = 0;
return false;
}
return true;
}
//---------------------------------------------------------
// ~Pdf
//---------------------------------------------------------
Pdf::~Pdf()
{
if (doc)
fz_close_document(doc);
doc = 0;
--references;
if (references == 0) {
fz_free_context(ctx);
ctx = 0;
}
}
//---------------------------------------------------------
// page
//---------------------------------------------------------
QImage Pdf::page(int i)
{
fz_page* page = fz_load_page(doc, i);
if (page == 0) {
printf("cannot load page %d\n", i);
return QImage();
}
static const float resolution = 600.0;
const float zoom = resolution / 72.0;
fz_rect bounds;
fz_bound_page(doc, page, &bounds);
fz_matrix ctm;
fz_pre_scale(fz_rotate(&ctm, 0.0), zoom, zoom);
fz_irect ibounds;
fz_rect tbounds;
tbounds = bounds;
fz_round_rect(&ibounds, fz_transform_rect(&tbounds, &ctm));
fz_pixmap* pix = fz_new_pixmap_with_bbox(ctx, fz_device_gray, &ibounds);
fz_clear_pixmap_with_value(ctx, pix, 255);
fz_device* dev = fz_new_draw_device(ctx, pix);
fz_run_page(doc, page, dev, &ctm, NULL);
fz_free_device(dev);
dev = NULL;
int w = fz_pixmap_width(ctx, pix);
int h = fz_pixmap_height(ctx, pix);
if (fz_pixmap_components(ctx, pix) != 2) {
printf("omg: pixmap not bw? %d\n", fz_pixmap_components(ctx, pix));
return QImage();
}
printf("page %d %d x %d\n", i, w, h);
QImage image(w, h, QImage::Format_MonoLSB);
QVector<QRgb> ct(2);
ct[0] = qRgb(255, 255, 255);
ct[1] = qRgb(0, 0, 0);
image.setColorTable(ct);
uchar* s = fz_pixmap_samples(ctx, pix);
int bytes = w / 8;
int bits = w % 8;
for (int line = 0; line < h; ++line) {
uchar* d = image.scanLine(line);
for (int col = 0; col < bytes; ++col) {
uchar data = 0;
for (int i = 0; i < 8; ++i) {
uchar v = *s;
s += 2;
data >>= 1;
if (v < 128) { // convert grayscale to bw
data |= 0x80;
}
}
*d++ = data;
}
uchar data = 0;
for (int col = 0; col < bits; ++col) {
uchar v = *s;
s += 2;
data >>= 1;
if (v < 128)
data |= 0x80;
}
}
fz_drop_pixmap(ctx, pix);
return image;
}
}