fonzie
clone your own copy | download snapshot

Snapshots | iceberg

No images in this repository’s iceberg at this time

Inside this repository

glyphtrace.cpp
text/x-c++src

Download raw (5.9 KB)

/***************************************************************************
 *   Copyright (C) 2010 by Pierre Marchand   *
 *   pierre@oep-h.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "glyphtrace.h"
#include "potrace_util.h"
#include "bitmap.h"

#include <iostream>
#include <QTransform>

#include <cstdio>
#include <cmath>

#include <QDebug>

#define DEFAULTXADVANCE 1000.0
#define MINIMUMIMAGEAREA 10000.0


GlyphTrace::GlyphTrace(QImage image, const Options& opt)
{
        static int img_ctr = 0;
	double iHeight(image.height());
	double iWidth(image.width());
	if(iHeight * iWidth > MINIMUMIMAGEAREA)
		iScale = 1.0;
	else
	{
		iScale = qMax(sqrt(MINIMUMIMAGEAREA / (iHeight * iWidth)), 0.000001);
	}
//	qDebug()<<iWidth<<iHeight<<iScale<< (iWidth * iScale) << (iHeight * iScale);
	bitmap = toBitmap(image.scaled(iWidth * iScale, iHeight * iScale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
	advance = DEFAULTXADVANCE;
	tx = ty = 0;
	potrace_param_t * par = potrace_param_default();
	par->progress.callback = captureTraceProgress;
	par->progress.min = 0;
	par->progress.max = 100;
	par->progress.epsilon = 0;
	par->progress.data = 0;
	par->alphamax = opt.alphamax;
	par->turdsize = opt.turdsize;
	par->opticurve = opt.opticurve;
	par->opttolerance = opt.opttolerance;

	potrace_bitmap_t * pbm(bm_new(bitmap.width(), bitmap.height()));
	bm_clear(pbm, 0);
	for(unsigned short i=0; i < pbm->h; ++i)
	{
		for(unsigned short j=0; j < pbm->w; ++j)
		{
//			if(bitmap.pixelIndex(j,i) > 0)
//				potrace_clear_pixel(pbm, j, (pbm->h - 1) - i);
//			else
//				potrace_set_pixel(pbm, j, (pbm->h - 1) - i);
			if(bitmap.pixelIndex(j,i) == 0)
				BM_SET(pbm, j, (pbm->h - 1) - i);
		}
	}
	image.save(QString("%1_image.png").arg(int(img_ctr++)));
//	bitmap.save(QString("%1_bitmap.png").arg(int(this)));
	potrace_state_t *pState = potrace_trace(par, pbm);
	potrace_path_t * p = pState->plist;
	while(p != 0)
	{
		storeCurve(&p->curve);
		p = p->next;
	}
	potrace_state_free(pState);
	potrace_param_free(par);
	bm_free(pbm);
	bitmap = QImage();
}

GlyphTrace * GlyphTrace::Clone()
{
	GlyphTrace * ret = new GlyphTrace;
//	ret->bitmap = bitmap;
	ret->gstore = gstore;
	ret->outline = outline;
	ret->glyphName = glyphName;
	ret->hexcode = hexcode;
	ret->scale = scale;
	ret->advance = advance;
	ret->tx = tx;
	ret->ty = ty;
	return ret;
}


bool GlyphTrace::Glyph()
{
	outline.clear();
	if(gstore.isEmpty())
		return false;

	QTransform t;
	t.translate(tx, ty);
	t.scale(scale, scale);
	QPainterPath path(t.map(gstore));
//	qDebug()<<glyphName<<t;

	outline +=  "\n<outline><contour>\n";
	QPointF curPos;
	QString move("<point x=\"%1\" y=\"%2\" type=\"move\"/>\n");
	QString line("<point x=\"%1\" y=\"%2\" type=\"line\" smooth=\"no\"/>\n");
	QString curve("<point x=\"%1\" y=\"%2\"/>\n<point x=\"%3\" y=\"%4\"/>\n<point x=\"%5\" y=\"%6\" type=\"curve\" smooth=\"yes\"/>\n");
	for (int i = 0; i < path.elementCount(); ++i)
	{
		QPainterPath::Element cur = path.elementAt(i);
		QPointF curPoint(cur);
		if(cur.isMoveTo())
		{
			curPos = curPoint;
			if(0 != i)
			{
				outline +=  "</contour>\n";
				outline +=  "<contour>\n";
			}
//			outline += move.arg(curPos.x()).arg(curPos.y());
		}
		else if(cur.isLineTo())
		{
			curPos = curPoint;
			outline += line.arg(qRound(curPos.x())).arg(qRound(curPos.y()));
		}
		else if(cur.isCurveTo())
		{
			QPointF c1 = path.elementAt(i + 1);
			QPointF c2 = path.elementAt(i + 2);
			outline += curve.arg(qRound(curPoint.x())).arg(qRound(curPoint.y()))
					.arg(qRound(c1.x())).arg(qRound(c1.y()))
					.arg(qRound(c2.x())).arg(qRound(c2.y()));
			i += 2;
			curPos = c2;
		}
		else
			qDebug("Unknown point type");
	}
	outline +=  "\n</contour>\n</outline>";

	return true;
}

QPointF GlyphTrace::GetPoint(potrace_dpoint_t c)
{
	QPointF ret(c.x / iScale, c.y / iScale);
	return ret;
}

void GlyphTrace::storeCurve(potrace_curve_t *c)
{
	gstore.moveTo(GetPoint(c->c[c->n-1][2]));
	for(int i=0; i < c->n; ++i)
	{
		if(c->tag[i] == POTRACE_CURVETO)
		{
			gstore.cubicTo(GetPoint(c->c[i][0]),  GetPoint(c->c[i][1]), GetPoint(c->c[i][2]));
		}
		else // CORNER
		{
			gstore.lineTo(GetPoint(c->c[i][1]));
			gstore.lineTo(GetPoint(c->c[i][2]));
		}
	}
}

QImage GlyphTrace::toBitmap(const QImage &i)
{
	QImage r(i.size(),QImage::Format_Mono);
	int dMax(255);
	int h(r.height());
	int w(r.width());
	for(unsigned int y=0; y < h; ++y)
	{
		for(unsigned int x=0; x < w; ++x)
		{
			if(qGray(i.pixel(x,y)) < dMax)
				dMax = qGray(i.pixel(x,y));

		}
	}
	int limit = 255 - ((255 - dMax) / 2);
//	qDebug()<<"limit"<<limit;
	for(unsigned int y=0; y < h; ++y)
	{
		for(unsigned int x=0; x < w; ++x)
		{
			if(qGray(i.pixel(x,y)) < limit)
				r.setPixel(x,y, 0);
			else
				r.setPixel(x,y, 1);

		}
	}
	return r;
}

void GlyphTrace::captureTraceProgress(double d, void *v)
{
	//todo
}