diff --git a/demo/fitGlyf.html b/demo/fitGlyf.html new file mode 100644 index 0000000..5770d9d --- /dev/null +++ b/demo/fitGlyf.html @@ -0,0 +1,75 @@ + + + + + canvas读取图片 + + + + + + + + + +
+
+ +
+ + + + + + diff --git a/demo/js/findBreakPoint.js b/demo/js/findBreakPoint.js index b5e2e7c..f58d247 100644 --- a/demo/js/findBreakPoint.js +++ b/demo/js/findBreakPoint.js @@ -8,7 +8,7 @@ define( var fitBezier = require('graphics/image/fitBezier'); var findBreakPoints = require('graphics/image/findBreakPoints'); var pathUtil = require('graphics/pathUtil'); - var data = require('demo/../data/image-contours1'); + var data = require('demo/../data/image-contours2'); var drawPath = require('render/util/drawPath'); var entry = { diff --git a/demo/js/fitCircle.js b/demo/js/fitCircle.js index 53f9710..849701e 100644 --- a/demo/js/fitCircle.js +++ b/demo/js/fitCircle.js @@ -72,54 +72,6 @@ define( var radius = dist(points[0], points[1]); ctx.arc(points[0].x, points[0].y, radius, 0, 180); ctx.stroke(); - - // var curvePoints = []; - // var count = 40; - // var tSegment = 1 / count; - // for (var i = 0; i < count; i++) { - // var t = tSegment * i; - // curvePoints.push({ - // x: points[0].x * B0(t) + points[1].x * B1(t) + points[2].x * B2(t) + points[3].x * B3(t), - // y: points[0].y * B0(t) + points[1].y * B1(t) + points[2].y * B2(t) + points[3].y * B3(t) - // }); - // } - - // ctx.fillStyle='green'; - // for (var i = 0; i < count; i++) { - // ctx.fillRect(curvePoints[i].x, curvePoints[i].y, 2, 2); - // } - - // var result = fitCurve(lang.clone(curvePoints), count); - // result.unshift(points[0]); - // //console.log(result); - - // ctx.beginPath(); - // ctx.strokeStyle='blue'; - // //ctx.translate(0, 10); - // ctx.moveTo(result[0].x, result[0].y); - // for (var i = 1; i < result.length - 1; i+=3) { - // ctx.bezierCurveTo(result[i].x, result[i].y, result[i + 1].x, result[i + 1].y, result[i + 2].x, result[i + 2].y); - // ctx.moveTo(result[i + 2].x, result[i + 2].y); - // } - - // ctx.stroke(); - - // var bezierResult = fitBezier(lang.clone(curvePoints)); - // bezierResult.unshift(curvePoints[0]); - // ctx.beginPath(); - // ctx.strokeStyle='yellow'; - // //ctx.translate(0, 10); - // ctx.moveTo(bezierResult[0].x, bezierResult[0].y); - // var last = bezierResult.length - 1; - // console.log(bezierResult.length); - // for (var i = 1; i < last; i+=2) { - // ctx.quadraticCurveTo(bezierResult[i].x, bezierResult[i].y, bezierResult[i + 1].x, bezierResult[i + 1].y); - // ctx.moveTo(bezierResult[i + 1].x, bezierResult[i + 1].y); - // } - - // ctx.stroke(); - - //ctx.translate(0, -20); } draw(); diff --git a/demo/js/fitContours.js b/demo/js/fitContours.js index a439542..f2c4d1c 100644 --- a/demo/js/fitContours.js +++ b/demo/js/fitContours.js @@ -6,108 +6,10 @@ define( function (require) { - var fitBezier = require('graphics/image/fitBezier'); - var findBreakPoints = require('graphics/image/findBreakPoints'); - var pathUtil = require('graphics/pathUtil'); - var vector = require('graphics/vector'); - var data = require('demo/../data/image-contours1'); + var fitContour = require('graphics/image/fitContour'); + var data = require('demo/../data/image-contours2'); var drawPath = require('render/util/drawPath'); - - var bezierCurvePointsArray = []; - - function fitContour(data) { - - data = pathUtil.scale(data, 10); - var breakPoints = findBreakPoints(data); - - breakPoints.forEach(function (p) { - console.log(p.right); - }); - - var resultContour = []; - var isLast; - var start; - var end; - var tHat1Point; - for (var i = 0, l = breakPoints.length; i < l; i++) { - isLast = i === l - 1; - start = breakPoints[i]; - end = breakPoints[ isLast ? 0 : i + 1]; - - resultContour.push({ - x: start.x, - y: start.y, - onCurve: true - }); - - if (start.right !== 1) { - - if (isLast) { - var curvePoints = data.slice(start.index).concat(data.slice(0, end.index)); - } - else { - var curvePoints = data.slice(start.index, end.index + 1); - } - - var bezierCurvePoints = []; - var curvePointsLast = curvePoints.length - 1; - - if (curvePoints.length > 200) { - var derive = Math.floor(curvePoints.length / 10); - bezierCurvePoints = curvePoints.filter(function (p, index) { - return index === 0 || index === curvePointsLast || p.index % derive === 0; - }); - } - else if (curvePoints.length > 30) { - var derive = Math.floor(curvePoints.length / 5); - bezierCurvePoints = curvePoints.filter(function (p, index) { - return index === 0 || index === curvePointsLast || p.index % derive === 0; - }); - } - else { - bezierCurvePoints = curvePoints.filter(function (p, index) { - return index === 0 || index === curvePointsLast || p.index % 5 === 0; - }); - } - - if ((start.tangency || start.inflexion) && tHat1Point) { - tHat1 = vector.normalize({ - x: start.x - tHat1Point.x, - y: start.y - tHat1Point.y - }); - } - else { - tHat1 = null; - } - - bezierCurvePoints.forEach(function (p) { - bezierCurvePointsArray.push(p); - }); - - var bezierCurve = fitBezier(bezierCurvePoints, 10, tHat1); - if (bezierCurve.length) { - bezierCurve.forEach(function (p) { - resultContour.push(p); - }); - tHat1Point = bezierCurve[bezierCurve.length - 2]; - } - else { - tHat1Point = null; - } - } - else { - tHat1Point = start; - } - } - - resultContour = pathUtil.scale(resultContour, 0.1); - data = pathUtil.scale(data, 0.1); - - return resultContour; - } - - var entry = { /** @@ -132,13 +34,9 @@ define( $('#points').html(html); html = ''; - bezierCurvePointsArray.forEach(function (p) { - html += ''; - }); - var ctx = $('#canvas').get(0).getContext('2d'); - ctx.strokeStyle = 'yellow'; + ctx.strokeStyle = 'pink'; contours.forEach(function (contour) { for (var i = 0, l = contour.length; i < l; i++) { diff --git a/demo/js/fitGlyf.js b/demo/js/fitGlyf.js new file mode 100644 index 0000000..b0c4041 --- /dev/null +++ b/demo/js/fitGlyf.js @@ -0,0 +1,119 @@ +/** + * @file 拟合图像字形 + * @author mengke01(kekee000@gmail.com) + */ + +define( + function (require) { + + var fitContour = require('graphics/image/fitContour'); + var image2Values = require('graphics/image/image2Values'); + var findContours = require('graphics/image/findContours'); + var computeBoundingBox = require('graphics/computeBoundingBox'); + var pathAdjust = require('graphics/pathAdjust'); + var drawPath = require('render/util/drawPath'); + var data = require('demo/../data/image-contours2'); + + var editor = require('editor/main'); + + var ctx = null; + + function fitGlyf(data) { + var html = ''; + var contours = []; + data.forEach(function(contour) { + contour.forEach(function (p) { + html += ''; + }); + contours.push(fitContour(contour)); + }); + + $('#points').html(html); + + html = ''; + ctx.beginPath(); + ctx.clearRect(0,0, 1000, 1000); + ctx.strokeStyle = 'pink'; + contours.forEach(function (contour) { + for (var i = 0, l = contour.length; i < l; i++) { + html += ''; + } + drawPath(ctx, contour); + }); + + ctx.stroke(); + + $('#points-break').html(html); + + var bound = computeBoundingBox.computePath.apply(null, contours); + + window.editor.setFont({ + contours: contours.map(function (contour) { + pathAdjust(contour, 1, -1); + pathAdjust(contour, 1, 1, 0, bound.height); + return contour; + }) + }); + } + + function findImageContours(imgData) { + var result = image2Values(imgData); + var contours = findContours(result); + + fitGlyf(contours); + } + + + + function onUpFileChange(e) { + var file = e.target.files[0]; + var reader = new FileReader(); + reader.onload = function(e) { + + var image = new Image(); + image.onload = function () { + ctx.clearRect(0,0, 1000, 1000); + ctx.drawImage(image, 0, 0, image.width, image.height); + findImageContours(ctx.getImageData(0, 0, image.width, image.height)); + }; + + image.src = e.target.result; + } + + reader.onerror = function(e) { + console.error(e); + }; + + reader.readAsDataURL(file); + } + + var entry = { + + /** + * 初始化 + */ + init: function () { + + window.editor = editor.create($('#render-view').get(0)); + + var upFile = document.getElementById('upload-file'); + upFile.addEventListener('change', onUpFileChange); + + ctx = $('#canvas').get(0).getContext('2d'); + + if (data) { + data.forEach(function(contour) { + contour.splice(contour.length - 1, 1); + }); + + fitGlyf(data); + } + } + + }; + + entry.init(); + + return entry; + } +); diff --git a/src/graphics/image/findBreakPoints.js b/src/graphics/image/findBreakPoints.js index 8b811b7..9fc600f 100644 --- a/src/graphics/image/findBreakPoints.js +++ b/src/graphics/image/findBreakPoints.js @@ -30,7 +30,7 @@ define( } function isLine(p0, p1, p) { - return 1 - absCos(p0, p1, p) < 0.01; + return 1 - absCos(p0, p1, p) < 0.004; } function isPerfectLine(p0, p1, p) { @@ -212,7 +212,9 @@ define( breakPoints = removeInflexionPoint(breakPoints, contour); - return breakPoints; + return breakPoints.sort(function (a, b) { + return a.index - b.index; + }); } /** diff --git a/src/graphics/image/findContours.js b/src/graphics/image/findContours.js index 64a8094..a0a5d9b 100644 --- a/src/graphics/image/findContours.js +++ b/src/graphics/image/findContours.js @@ -99,7 +99,7 @@ define( x: x, y: y }, true); - contours.push(contour); + contour && contours.push(contour); } } @@ -111,7 +111,7 @@ define( x: x - 1, y: y }, true); - contours.push(contour.reverse()); + contour && contours.push(contour.reverse()); } } } diff --git a/src/graphics/image/fitContour.js b/src/graphics/image/fitContour.js new file mode 100644 index 0000000..1699d76 --- /dev/null +++ b/src/graphics/image/fitContour.js @@ -0,0 +1,105 @@ +/** + * @file 根据关键点数据拟合轮廓 + * @author mengke01(kekee000@gmail.com) + */ + + +define( + function (require) { + + var fitBezier = require('graphics/image/fitBezier'); + var findBreakPoints = require('graphics/image/findBreakPoints'); + var pathUtil = require('graphics/pathUtil'); + var vector = require('graphics/vector'); + + + function fitContour(data) { + + data = pathUtil.scale(data, 10); + + var breakPoints = findBreakPoints(data); + + var resultContour = []; + var isLast; + var start; + var end; + var curvePoints; + var tHat1Point; + + for (var i = 0, l = breakPoints.length; i < l; i++) { + isLast = i === l - 1; + start = breakPoints[i]; + end = breakPoints[ isLast ? 0 : i + 1]; + + resultContour.push({ + x: start.x, + y: start.y, + onCurve: true + }); + + if (start.right !== 1) { + + if (isLast) { + curvePoints = data.slice(start.index).concat(data.slice(0, end.index)); + } + else { + curvePoints = data.slice(start.index, end.index + 1); + } + + var bezierCurvePoints = []; + var curvePointsLast = curvePoints.length - 1; + + if (curvePoints.length > 200) { + var derive = Math.floor(curvePoints.length / 20); + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % derive === 0; + }); + } + else if (curvePoints.length > 40) { + var derive = Math.floor(curvePoints.length / 10); + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % derive === 0; + }); + } + else { + bezierCurvePoints = curvePoints.filter(function (p, index) { + return index === 0 || index === curvePointsLast || p.index % 5 === 0; + }); + } + + if (start.tangency && tHat1Point) { + tHat1 = vector.normalize({ + x: start.x - tHat1Point.x, + y: start.y - tHat1Point.y + }); + } + else { + tHat1 = null; + } + + var bezierCurve = fitBezier(bezierCurvePoints, 10, tHat1); + if (bezierCurve.length) { + bezierCurve.forEach(function (p) { + resultContour.push(p); + }); + tHat1Point = bezierCurve[bezierCurve.length - 2]; + } + else { + tHat1Point = null; + } + } + else { + tHat1Point = start; + } + } + + resultContour = pathUtil.scale(resultContour, 0.1); + + data = pathUtil.scale(data, 0.1); + + return resultContour; + } + + return fitContour; + } +); diff --git a/src/graphics/image/fitCurve.js b/src/graphics/image/fitCurve.js index d5885b1..b4667ff 100644 --- a/src/graphics/image/fitCurve.js +++ b/src/graphics/image/fitCurve.js @@ -267,8 +267,8 @@ define( /* Generate control vertices for Q'' */ for (i = 0; i <= 1; i++) { Q2[i] = { - x: (Q[i + 1].x - Q[i].x) * 2.0, - y: (Q[i + 1].y - Q[i].y) * 2.0 + x: (Q[i + 1].x - Q[i].x) * 6.0, + y: (Q[i + 1].y - Q[i].y) * 6.0 }; } diff --git a/test/ecomfe.png b/test/ecomfe.png new file mode 100644 index 0000000..1278d09 Binary files /dev/null and b/test/ecomfe.png differ