Прежде всего: что я пытаюсь сделать?
У меня есть приложение для просмотра изображений. Он использует элемент canvas для визуализации изображения. Вы можете увеличить, вы можете уменьшить масштаб, и вы можете перетащить его. Эта часть отлично работает прямо сейчас.
Но позвольте мне сказать, что у меня есть изображение с большим количеством текста. У него разрешение 1200х1700, а у моего холста 1200х900. Первоначально при уменьшении это приводит к разрешению ~ 560x800.
Мой фактический рисунок выглядит так:
drawImage(src, srcOffsetX, srcOffsetY, sourceViewWidth, sourceViewHeight,
destOffsetX, destOffsetY, destWidth, destHeight);
Небольшой текст на этом изображении выглядит очень, очень плохо, особенно по сравнению с другими программами просмотра изображений (например, IrfanView) или даже элементом html <img>.
Я понял, что причиной этой проблемы является алгоритм интерполяции браузеров. Сравнение различных браузеров показало, что Chrome отображает масштабированные изображения лучше, но все еще недостаточно хорош.
Ну, я искал в каждом углу Interwebs в течение 4-5 часов подряд и не нашел то, что мне нужно. Я нашел вариант "imageSmoothingEnabled", "образ-рендеринг" стили CSS, которые вы не можете использовать на холсте, рендеринг в поплавковой позиции и многих реализациях JavaScript алгоритмов интерполяции (те далеки, чтобы замедлить для моей цели).
Вы можете спросить, почему я говорю вам все это: чтобы сэкономить время, чтобы дать мне ответы, которые я уже знаю
Итак: есть ли хороший и быстрый способ улучшить интерполяцию? Моя текущая идея состоит в том, чтобы создать объект изображения, изменить его размер (потому что img имеет хорошую интерполяцию при масштабировании!) И затем отобразить его. К сожалению, применение img.width влияет только на отображаемую ширину...
Обновление: благодаря Саймону я смог решить мою проблему. Вот алгоритм динамического масштабирования, который я использовал. Обратите внимание, что он сохраняет соотношение сторон, параметр height предназначен только для избежания дополнительных вычислений с плавающей запятой. Это только уменьшится прямо сейчас.
scale(destWidth, destHeight){
var start = new Date().getTime();
var scalingSteps = 0;
var ctx = this._sourceImageCanvasContext;
var curWidth = this._sourceImageWidth;
var curHeight = this._sourceImageHeight;
var lastWidth = this._sourceImageWidth;
var lastHeight = this._sourceImageHeight;
var end = false;
var scale=0.75;
while(end==false){
scalingSteps +=1;
curWidth *= scale;
curHeight *= scale;
if(curWidth < destWidth){
curWidth = destWidth;
curHeight = destHeight;
end=true;
}
ctx.drawImage(this._sourceImageCanvas, 0, 0, Math.round(lastWidth), Math.round(lastHeight), 0, 0, Math.round(curWidth), Math.round(curHeight));
lastWidth = curWidth;
lastHeight = curHeight;
}
var endTime =new Date().getTime();
console.log("execution time: "+ ( endTime - start) + "ms. scale per frame: "+scale+ " scaling step count: "+scalingSteps);
}