जावास्क्रिप्ट में छवि डेटा यूआरएल प्राप्त करें?


335

मेरे पास कुछ छवियों (बस नियमित <img />HTML टैग) के साथ एक नियमित HTML पृष्ठ है । मैं उनकी सामग्री प्राप्त करना चाहूंगा, छवि को फिर से डाउनलोड करने की आवश्यकता के बिना, बेस 64 को एन्कोड किया गया है (यानी यह पहले से ही ब्राउज़र द्वारा लोड किया गया है, इसलिए अब मुझे सामग्री चाहिए)।

मुझे Greasemonkey और फ़ायरफ़ॉक्स के साथ यह हासिल करना अच्छा लगेगा।

जवाबों:


400

नोट: यह केवल तभी काम करता है जब छवि पृष्ठ के समान डोमेन से हो या जिसमें crossOrigin="anonymous"विशेषता हो और सर्वर कोर का समर्थन करता हो। यह आपको मूल फ़ाइल भी नहीं देने जा रहा है, लेकिन फिर से एन्कोडेड संस्करण है। यदि आपको परिणाम मूल के समान होने की आवश्यकता है, तो काइडो का उत्तर देखें


आपको सही आयामों के साथ एक कैनवास तत्व बनाने और drawImageफ़ंक्शन के साथ छवि डेटा की प्रतिलिपि बनाने की आवश्यकता होगी । फिर आप toDataURLडेटा प्राप्त करने के लिए फ़ंक्शन का उपयोग कर सकते हैं : url जिसमें बेस -64 एन्कोडेड छवि है। ध्यान दें कि छवि पूरी तरह से भरी होनी चाहिए, या आपको बस एक खाली (काली, पारदर्शी) छवि मिल जाएगी।

यह कुछ इस तरह होगा। मैंने कभी Greasemonkey स्क्रिप्ट नहीं लिखी है, इसलिए आपको उस वातावरण में चलने के लिए कोड को समायोजित करने की आवश्यकता हो सकती है।

function getBase64Image(img) {
    // Create an empty canvas element
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    // Copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    // Get the data-URL formatted image
    // Firefox supports PNG and JPEG. You could check img.src to
    // guess the original format, but be aware the using "image/jpg"
    // will re-encode the image.
    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

JPEG- स्वरूपित छवि प्राप्त करना फ़ायरफ़ॉक्स के पुराने संस्करणों (लगभग 3.5) पर काम नहीं करता है, इसलिए यदि आप इसका समर्थन करना चाहते हैं, तो आपको संगतता की जांच करनी होगी। यदि एन्कोडिंग समर्थित नहीं है, तो यह "छवि / पीएनजी" के लिए डिफ़ॉल्ट होगा।


1
हालांकि यह काम करता हुआ प्रतीत होता है (बिना बदले में / वापसी में), यह एक ही बेस 64 स्ट्रिंग नहीं बनाता है, जैसा कि मुझे PHP से मिल रहा है जब फ़ाइल_get_contents फ़ंक्शन के साथ प्राप्त फ़ाइल पर base64_encode कर रहा है। छवियां बहुत समान / समान लगती हैं, फिर भी जावास्क्रिप्ट एक छोटा है और मैं उन्हें बिल्कुल वैसा ही बनना पसंद करूंगा। एक और बात: इनपुट छवि एक छोटी (594 बाइट्स), पारदर्शी पृष्ठभूमि वाली 28x30 पीएनजी है - यदि वह कुछ भी बदलती है।
डेट्रायेल

7
फ़ायरफ़ॉक्स एक अलग संपीड़न स्तर का उपयोग कर सकता है जो एन्कोडिंग को प्रभावित करेगा। इसके अलावा, मुझे लगता है कि पीएनजी नोटों जैसी कुछ अतिरिक्त हेडर सूचनाओं का समर्थन करता है, जो खो जाएगा, क्योंकि कैनवास केवल पिक्सेल डेटा प्राप्त करता है। यदि आपको इसकी आवश्यकता बिल्कुल वैसी ही है, तो आप शायद फ़ाइल प्राप्त करने के लिए AJAX का उपयोग कर सकते हैं और बेस 64 इसे मैन्युअल रूप से एनकोड कर सकते हैं।
मैथ्यू क्रूले

7
हां, आप छवि को XMLHttpRequest के साथ डाउनलोड करेंगे। उम्मीद है, यह छवि के कैश्ड संस्करण का उपयोग करेगा, लेकिन यह सर्वर और ब्राउज़र कॉन्फ़िगरेशन पर निर्भर करेगा, और यदि फ़ाइल बदल गई है, तो यह निर्धारित करने के लिए आपके पास अनुरोध ओवरहेड होगा। इसलिए मैंने सुझाव नहीं दिया कि पहली जगह में :-) दुर्भाग्य से, जहाँ तक मुझे पता है, यह मूल फ़ाइल प्राप्त करने का एकमात्र तरीका है।
मैथ्यू क्रुमले

2
@trusktr drawImageकुछ नहीं करेगा, और आप एक रिक्त कैनवास और परिणामस्वरूप छवि के साथ समाप्त करेंगे।
मैथ्यू क्रूले

1
@ जॉनसनवेल यह केवल इसलिए है क्योंकि ओपी सामग्री चाहता था, URL नहीं। यदि आप इसे एक छवि स्रोत के रूप में उपयोग करना चाहते हैं, तो आपको प्रतिस्थापित (...) कॉल को छोड़ना होगा।
मैथ्यू क्रुमले

76

यह फ़ंक्शन URL लेता है फिर छवि BASE64 लौटाता है

function getBase64FromImageUrl(url) {
    var img = new Image();

    img.setAttribute('crossOrigin', 'anonymous');

    img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");

        alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
    };

    img.src = url;
}

इसे इस तरह से कॉल करें: getBase64FromImageUrl("images/slbltxt.png")


8
क्या बाहरी लिंक से आधार 64 तक एक छवि को चालू करने का एक तरीका है?
दिनोदोरस

@dinodsaurus आप इसे एक छवि टैग में लोड कर सकते हैं, या एक अजाक्स क्वेरी कर सकते हैं।
जारेड फोर्सिथ

6
ठीक है, इसके लिए उन्हें CORS लागू करने की आवश्यकता होती है, लेकिन तब आप केवल $ .ajax (theimageurl) करते हैं और इसे कुछ उचित वापस करना चाहिए। अन्यथा (यदि उनके पास कॉर्स सक्षम नहीं है) यह काम नहीं करेगा; इंटरनेट का सुरक्षा मॉडल इसे अस्वीकार कर देता है। जब तक, निश्चित रूप से, आप एक क्रोम प्लगइन के अंदर हैं, जिस स्थिति में सब कुछ अनुमति दी जाती है - यहां तक ​​कि उपरोक्त उदाहरण
जारेड फोर्सिथ

4
आपको img.src =बाद में रखना होगा img.onload =, क्योंकि कुछ ब्राउज़र, जैसे ओपेरा में, घटना नहीं होगी।
शाम

1
@ हक्कर स्मृति रिसाव केवल पुराने ब्राउज़रों में होगा जो कचरा संग्रह को सूचित करने के लिए अभी भी संदर्भ संख्या का उपयोग करते हैं । मेरी समझ से परिपत्र संदर्भ एक निशान और स्वीप सेटअप में रिसाव पैदा नहीं करता है । एक बार जब कार्यों के स्कोप getBase64FromImageUrl(url)और img.onload = function ()बाहर निकल जाते हैं तो अप्राप्य और कचरा एकत्र हो जाता है। IE 6/7 के अलावा और यह ठीक है।
मानवतावादी

59

लंबे समय के बाद आ रहा है, लेकिन यहां कोई भी जवाब पूरी तरह से सही नहीं है।

जब एक कैनवास पर खींचा जाता है, तो पारित छवि असम्पीडित होती है + सभी पूर्व-गुणा।
जब निर्यात किया जाता है, तो इसके असम्पीडित या एक अलग एल्गोरिथ्म के साथ recompressed, और अन-गुणा।

इस प्रक्रिया में सभी ब्राउज़रों और उपकरणों में अलग-अलग राउंडिंग त्रुटियाँ होंगी
(देखें कैनवस फ़िंगरप्रिंटिंग )।

इसलिए यदि कोई एक छवि फ़ाइल का एक आधार संस्करण चाहता है, तो उन्हें इसे फिर से अनुरोध करना होगा (अधिकांश समय यह कैश से आएगा) लेकिन इस बार एक बूँद के रूप में।

फिर आप इसे एक ArrayBuffer के रूप में, या एक dataURL के रूप में पढ़ने के लिए FileReader का उपयोग कर सकते हैं ।

function toDataURL(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open('get', url);
    xhr.responseType = 'blob';
    xhr.onload = function(){
      var fr = new FileReader();
    
      fr.onload = function(){
        callback(this.result);
      };
    
      fr.readAsDataURL(xhr.response); // async call
    };
    
    xhr.send();
}

toDataURL(myImage.src, function(dataURL){
  result.src = dataURL;

  // now just to show that passing to a canvas doesn't hold the same results
  var canvas = document.createElement('canvas');
  canvas.width = myImage.naturalWidth;
  canvas.height = myImage.naturalHeight;
  canvas.getContext('2d').drawImage(myImage, 0,0);

  console.log(canvas.toDataURL() === dataURL); // false - not same data
  });
<img id="myImage" src="https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png" crossOrigin="anonymous">
<img id="result">


बस 5+ अलग-अलग प्रश्नों के माध्यम से गया और आपका कोड केवल वही है जो सही ढंग से काम किया है, धन्यवाद :)
पीटर

1
मुझे यह त्रुटि उपरोक्त कोड से मिली। XMLHttpRequest cannot load data:image/jpeg;base64,/9j/4AA ... /2Q==. Invalid response. Origin 'https://example.com' is therefore not allowed access.
STWilson

2
@STWillson, हाँ, यह विधि भी उसी तरह की मूल नीति से जुड़ी है, जैसे कैनवास एक। क्रॉस-ऑरिजनल रिक्वेस्ट के मामले में, आपको अपनी स्क्रिप्ट में ऐसे क्रॉस-ऑरिजिन रिक्वेस्ट को अनुमति देने के लिए होस्टिंग सर्वर को कॉन्फ़िगर करना होगा।
काइदो

@ कैइडो तो अगर स्क्रिप्ट स्क्रिप्ट की तुलना में किसी अन्य सर्वर पर छवि है तो होस्टिंग सर्वर को क्रॉस मूल अनुरोधों को सक्षम करना होगा? यदि आप सेट करते हैं img.setAttribute ('crossOrigin', 'अनाम') क्या त्रुटि को रोकता है?
1.21 गीगावाट

1
और अधिक शोध करने पर, यह छवि के अनुरोध का उपयोग करने के लिए crossOrigin विशेषता का उपयोग कर सकते हैं की तरह लग रहा है, लेकिन यह, एक CORS हेडर के माध्यम से पहुंच देने के लिए होस्टिंग सर्वर पर निर्भर है sitepoint.com/an-in-depth-look-at-cors । के रूप में XMLHttpRequest के लिए ऐसा लगता है कि सर्वर को कॉर्स हेडर के माध्यम से छवियों के लिए समान एक्सेस देना है, लेकिन शायद xhr.withCredentials को गलत (डिफ़ॉल्ट) सेट करने के अलावा आपके कोड में कोई बदलाव आवश्यक नहीं है।
1.21 गीगावाट

20

भ्रूण का उपयोग करके काइडो के उत्तर का एक और आधुनिक संस्करण होगा:

function toObjectUrl(url) {
  return fetch(url)
      .then((response)=> {
        return response.blob();
      })
      .then(blob=> {
        return URL.createObjectURL(blob);
      });
}

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

संपादित करें: जैसा कि टिप्पणियों में बताया गया है, यह एक वस्तु यूआरएल को लौटाएगा, जो आपके डेटा के उपयोग के मामले में आपके डेटा सिस्टम के बजाय आपके स्थानीय सिस्टम में एक फ़ाइल की ओर इंगित करता है, इसलिए यह वह नहीं हो सकता है जो आपको चाहिए।

आप भ्रूण और एक वास्तविक dataURL का उपयोग करने के लिए निम्नलिखित उत्तर देख सकते हैं: https://stackoverflow.com/a/50463054/599602


2
URL.revokeObjectURL()यदि आप इस पद्धति का उपयोग करके लंबे समय से चल रहे एप्लिकेशन को कॉल करना भूल जाते हैं , या आपकी मेमोरी बंद हो जाएगी।
इंजीनियर

1
ध्यान दें: DataURL (base64 एन्कोडेड) ObjectURL (बूँद के संदर्भ में) के समान नहीं है
DaniEll

1
ऑब्जेक्ट URL निश्चित रूप से डेटा URL नहीं है। यह सही जवाब नहीं है।
डैनी लिन

2

shiv / शिम / शम

यदि आपकी छवि पहले से लोड है (या नहीं), तो यह "उपकरण" काम में आ सकता है:

Object.defineProperty
(
    HTMLImageElement.prototype,'toDataURL',
    {enumerable:false,configurable:false,writable:false,value:function(m,q)
    {
        let c=document.createElement('canvas');
        c.width=this.naturalWidth; c.height=this.naturalHeight;
        c.getContext('2d').drawImage(this,0,0); return c.toDataURL(m,q);
    }}
);

.. लेकिन क्यों?

यह "पहले से लोड" छवि डेटा का उपयोग करने का लाभ है, इसलिए आवश्यक में कोई अतिरिक्त अनुरोध नहीं है। Aditionally यह अंत उपयोगकर्ता (आप की तरह प्रोग्रामर) तय कर सकते हैं CORS और / या mime-typeऔर quality-या- आप इन तर्कों / मानकों में वर्णित के रूप में बाहर छोड़ सकते हैं MDN विनिर्देश यहाँ

यदि आपके पास यह जेएस लोड किया गया है (जब यह आवश्यक हो तो पहले), तो इसे बदलना dataURLउतना ही सरल है:

उदाहरण

HTML
<img src="/yo.jpg" onload="console.log(this.toDataURL('image/jpeg'))">
JS
console.log(document.getElementById("someImgID").toDataURL());

GPU फिंगरप्रिंटिंग

यदि आप बिट्स की "पूर्वता" के बारे में चिंतित हैं तो आप इस उपकरण को अपनी आवश्यकताओं के अनुरूप बदल सकते हैं जैसा कि @ काइडो के उत्तर द्वारा प्रदान किया गया है।


1

onloadलोड करने के बाद छवि बदलने के लिए घटना का उपयोग करें


-3

HTML5 में इसका बेहतर उपयोग करें:

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}

2
प्रश्न का उत्तर देते समय अधिक विशिष्ट होने की कोशिश करें और विस्तृत विवरण प्रदान करें।
पीयूष जलानी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.