वजह
कुछ छवियों को बस नमूने के लिए बहुत मुश्किल है और इस तरह के एक के रूप में प्रक्षेपित करें जब आप बड़े आकार से छोटे तक जाना चाहते हैं।
ब्राउज़र आमतौर पर (संभावित) प्रदर्शन कारणों के लिए द्वि-घन (4x4 नमूना) के बजाय कैनवास तत्व के साथ द्वि-रैखिक (2x2 नमूनाकरण) प्रक्षेप का उपयोग करते दिखाई देते हैं।
यदि चरण बहुत बड़ा है, तो परिणाम के लिए पर्याप्त पिक्सेल नहीं हैं, जिससे नमूना लिया जा सके।
एक सिग्नल / डीएसपी के नजरिए से आप इसे कम-पास फिल्टर के थ्रेशोल्ड मान के रूप में बहुत अधिक सेट कर सकते हैं, जिसके परिणामस्वरूप सिग्नल में कई उच्च आवृत्तियों (विवरण) होने पर उर्फिंग हो सकती है।
उपाय
अपडेट 2018:
यहां एक साफ-सुथरी चाल है जो आप उन ब्राउज़रों के लिए उपयोग कर सकते हैं जो filter
2 डी संदर्भ पर संपत्ति का समर्थन करते हैं। यह उस छवि को पूर्व-धुंधला कर देता है जो कि एक रेज़मैपलिंग के समान है, फिर नीचे तराजू। यह बड़े चरणों के लिए अनुमति देता है लेकिन केवल दो चरणों और दो ड्रॉ की आवश्यकता होती है।
त्रिज्या के रूप में चरणों की मूल संख्या (मूल आकार / गंतव्य आकार / 2) का उपयोग करके पूर्व-धुंधला (आपको ब्राउज़र और विषम / यहां तक कि चरणों के आधार पर इसे व्यवस्थित रूप से समायोजित करने की आवश्यकता हो सकती है - यहां केवल सरलीकृत दिखाया गया है):
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (typeof ctx.filter === "undefined") {
alert("Sorry, the browser doesn't support Context2D filters.")
}
const img = new Image;
img.onload = function() {
const oc = document.createElement('canvas');
const octx = oc.getContext('2d');
oc.width = this.width;
oc.height = this.height;
const steps = (oc.width / canvas.width)>>1;
octx.filter = `blur(${steps}px)`;
octx.drawImage(this, 0, 0);
ctx.drawImage(oc, 0, 0, oc.width, oc.height, 0, 0, canvas.width, canvas.height);
}
img.src = "//i.stack.imgur.com/cYfuM.jpg";
body{ background-color: ivory; }
canvas{border:1px solid red;}
<br/><p>Original was 1600x1200, reduced to 400x300 canvas</p><br/>
<canvas id="canvas" width=400 height=250></canvas>
फिल्टर के लिए समर्थन के रूप में ogf Oct / 2018:
CanvasRenderingContext2D.filter
api.CanvasRenderingContext2D.filter
On Standard Track, Experimental
https:
DESKTOP > |Chrome |Edge |Firefox |IE |Opera |Safari
:----------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------
filter ! | 52 | ? | 49 | - | - | -
MOBILE > |Chrome/A |Edge/mob |Firefox/A |Opera/A |Safari/iOS|Webview/A
:----------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------
filter ! | 52 | ? | 49 | - | - | 52
! = Experimental
Data from MDN - "npm i -g mdncomp" (c) epistemex
अद्यतन 2017: अब एक नया गुण है जो गुणवत्ता को फिर से स्थापित करने के लिए ऐनक में परिभाषित किया गया है:
context.imageSmoothingQuality = "low|medium|high"
यह वर्तमान में केवल Chrome में समर्थित है। प्रति स्तर उपयोग की जाने वाली वास्तविक विधियां विक्रेता के पास तय करने के लिए छोड़ दी जाती हैं, लेकिन लैंक्ज़ोस को "उच्च" या गुणवत्ता में कुछ के बराबर मान लेना उचित है। इसका मतलब यह है कि स्टेप-डाउन को पूरी तरह से छोड़ दिया जा सकता है, या बड़े चरणों का उपयोग कम आकार के साथ किया जा सकता है, जो छवि आकार पर निर्भर करता है और
इसके लिए समर्थन imageSmoothingQuality
:
CanvasRenderingContext2D.imageSmoothingQuality
api.CanvasRenderingContext2D.imageSmoothingQuality
On Standard Track, Experimental
https:
DESKTOP > |Chrome |Edge |Firefox |IE |Opera |Safari
:----------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:
imageSmoothingQuality !| 54 | ? | - | ? | 41 | Y
MOBILE > |Chrome/A |Edge/mob |Firefox/A |Opera/A |Safari/iOS|Webview/A
:----------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:
imageSmoothingQuality !| 54 | ? | - | 41 | Y | 54
! = Experimental
Data from MDN - "npm i -g mdncomp" (c) epistemex
ब्राउज़र। तब तक ..:
ट्रांसमिशन का अंत
समाधान उचित परिणाम प्राप्त करने के लिए चरण-डाउन का उपयोग करना है। स्टेप-डाउन का मतलब है कि आप सीमित प्रक्षेप रेंज को नमूने के लिए पर्याप्त पिक्सेल कवर करने की अनुमति देने के लिए चरणों में आकार को कम करते हैं।
यह द्वि-रैखिक प्रक्षेप के साथ अच्छे परिणाम भी देगा (यह वास्तव में ऐसा करते समय द्वि-घन की तरह व्यवहार करता है) और ओवरहेड न्यूनतम है क्योंकि प्रत्येक चरण में नमूना करने के लिए कम पिक्सेल हैं।
आदर्श चरण प्रत्येक चरण में आधे रिज़ॉल्यूशन पर जाना है जब तक कि आप लक्ष्य आकार निर्धारित नहीं करेंगे (इस बात का उल्लेख करने के लिए जो मेबेल के लिए धन्यवाद!)।
संशोधित बेला
मूल प्रश्न के रूप में प्रत्यक्ष स्केलिंग का उपयोग करना:
नीचे दिखाए गए अनुसार स्टेप-डाउन का उपयोग करना:
इस स्थिति में आपको 3 चरणों में नीचे जाने की आवश्यकता होगी:
चरण 1 में हम ऑफ-स्क्रीन कैनवास का उपयोग करके छवि को आधा कर देते हैं:
var oc = document.createElement('canvas'),
octx = oc.getContext('2d');
oc.width = img.width * 0.5;
oc.height = img.height * 0.5;
octx.drawImage(img, 0, 0, oc.width, oc.height);
चरण 2 ऑफ-स्क्रीन कैनवास का पुन: उपयोग करता है और कम की गई छवि को फिर से आधे तक खींचता है:
octx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5);
और हम मुख्य कैनवास पर एक बार फिर से आकर्षित होते हैं, फिर से घटकर आधा हो जाता है , लेकिन अंतिम आकार में:
ctx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5,
0, 0, canvas.width, canvas.height);
टिप:
आप इस सूत्र का उपयोग करके आवश्यक कुल चरणों की गणना कर सकते हैं (इसमें लक्ष्य आकार निर्धारित करने के लिए अंतिम चरण शामिल है):
steps = Math.ceil(Math.log(sourceWidth / targetWidth) / Math.log(2))