জাভাস্ক্রিপ্টে চিত্রের ডেটা ইউআরএল পাবেন?


335

কিছু চিত্র সহ আমার নিয়মিত এইচটিএমএল পৃষ্ঠা রয়েছে (কেবলমাত্র নিয়মিত <img />এইচটিএমএল ট্যাগ)। আমি তাদের বিষয়বস্তুগুলি পেতে চাই, বেস 64 টি পছন্দমতোভাবে এনকোড করা হয়েছে, ছবিটি পুনরায় ডাউনলোড করার প্রয়োজন ছাড়াই (যেমন, এটি ইতিমধ্যে ব্রাউজার দ্বারা লোড করা হয়েছে, সুতরাং এখন আমি সামগ্রীটি চাই)।

আমি গ্রিসমোনকি এবং ফায়ারফক্সের সাথে এটি অর্জন করতে পছন্দ করব।

উত্তর:


400

দ্রষ্টব্য: এটি কেবলমাত্র তখনই কাজ করে যদি চিত্রটি পৃষ্ঠার মতো একই ডোমেন থেকে আসে বা crossOrigin="anonymous"বৈশিষ্ট্যটি থাকে এবং সার্ভারটি সিওআরএস সমর্থন করে। এটি আপনাকে মূল ফাইলটি দেবে না, তবে একটি পুনরায় এনকোড করা সংস্করণ। যদি ফলাফলটি মূলটির সাথে সাদৃশ্যপূর্ণ হওয়ার প্রয়োজন হয় তবে কইডোর উত্তর দেখুন


আপনাকে সঠিক মাত্রা সহ একটি ক্যানভাস উপাদান তৈরি করতে হবে এবং drawImageফাংশনটির সাথে চিত্রের ডেটা অনুলিপি করতে হবে। তারপরে আপনি toDataURLকোনও ডেটা পেতে ফাংশনটি ব্যবহার করতে পারেন : ইউআরএলটিতে বেস-64৪ এনকোডযুক্ত চিত্র রয়েছে। নোট করুন যে চিত্রটি অবশ্যই পুরোপুরি লোড হওয়া উচিত, অথবা আপনি খালি (কালো, স্বচ্ছ) চিত্রটি ফিরে পাবেন।

এটি এমন কিছু হবে। আমি কখনও গ্রিসমোনকি স্ক্রিপ্টটি লিখিনি, সুতরাং সেই পরিবেশে চালানোর জন্য আপনার কোডটি সামঞ্জস্য করতে হতে পারে।

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,/, "");
}

একটি জেপিজি-ফর্ম্যাটযুক্ত চিত্র পাওয়া ফায়ারফক্সের পুরানো সংস্করণগুলিতে (প্রায় 3.5) কাজ করে না, সুতরাং আপনি যদি এটি সমর্থন করতে চান তবে আপনাকে সামঞ্জস্যতা পরীক্ষা করতে হবে। যদি এনকোডিং সমর্থিত না হয় তবে এটি "চিত্র / পিএনজি" তে ডিফল্ট হবে।


1
যদিও এটি কাজ করছে বলে মনে হচ্ছে (অপরিবর্তিত / বিপরীতে বাদে), ফাইল_জেট_কন্টেন্টস ফাংশন সহ প্রাপ্ত ফাইলটিতে বেস64_encode করার সময় এটি পিএইচপি থেকে যেভাবে পাই সেভাবে একই বেস 64 স্ট্রিংটি তৈরি করে না। চিত্রগুলি দেখতে খুব একইরকম / একই রকম, তবুও জাভাস্ক্রিপ্টযুক্ত একটি ছোট এবং আমি তাদের ঠিক একইরকম হতে চাই। আরও একটি জিনিস: ইনপুট চিত্রটি একটি ছোট (594 বাইট), স্বচ্ছ ব্যাকগ্রাউন্ড সহ 28x30 পিএনজি - যদি এতে কিছু পরিবর্তন হয়।
ডিটারিয়েল

7
ফায়ারফক্স একটি আলাদা সংকোচনের স্তর ব্যবহার করতে পারে যা এনকোডিংকে প্রভাবিত করবে। এছাড়াও, আমি মনে করি পিএনজি নোটগুলির মতো কিছু অতিরিক্ত শিরোনামের তথ্য সমর্থন করে, যেগুলি নষ্ট হয়ে যাবে, যেহেতু ক্যানভাস কেবল পিক্সেল ডেটা পায়। আপনার যদি এটি হুবহু হ'ল প্রয়োজন হয়, আপনি সম্ভবত ফাইলটি পেতে অ্যাজাক্স ব্যবহার করতে পারেন এবং বেস 64 এটিকে ম্যানুয়ালি এনকোড করতে পারেন।
ম্যাথু ক্রামলে

7
হ্যাঁ, আপনি ছবিটি এক্সএমএলএইচটিপিআরকিউয়েস্টের সাথে ডাউনলোড করবেন। আশা করি, এটি চিত্রের ক্যাশেড সংস্করণটি ব্যবহার করবে তবে এটি সার্ভার এবং ব্রাউজার কনফিগারেশনের উপর নির্ভর করবে এবং ফাইলটি পরিবর্তন হয়েছে কিনা তা নির্ধারণ করার জন্য আপনার অনুরোধের ওভারহেড থাকবে। এই কারণেই আমি প্রথমে এটি প্রস্তাব করিনি :-) দুর্ভাগ্যক্রমে, যতদূর আমি জানি, এটি মূল ফাইলটি পাওয়ার একমাত্র উপায়।
ম্যাথু ক্রামলে

2
@trusktr drawImageএটি কিছুই করবে না, এবং আপনি একটি ফাঁকা ক্যানভাস এবং ফলস্বরূপ চিত্র সহ শেষ করবেন।
ম্যাথু ক্রামলে

1
@ জনসওয়েল এটি কেবল কারণ ওপি একটি সামগ্রী নয়, ইউআরএল চেয়েছিল। আপনি যদি ইমেজ উত্স হিসাবে এটি ব্যবহার করতে চান তবে আপনাকে প্রতিস্থাপন (...) কলটি এড়িয়ে যেতে হবে।
ম্যাথু ক্রামলে

76

এই ফাংশনটি ইউআরএল গ্রহণ করে তারপরে 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৪ তে ঘুরিয়ে দেওয়ার কোনও উপায় আছে?
ডায়নোডসরাসটি

@ জিনোদসরাস আপনি এটি কোনও চিত্র ট্যাগে লোড করতে বা একটি এজাক্স কোয়েরি করতে পারেন।
জ্যারেড ফোর্সিথ

6
ঠিক আছে, এটির জন্য তাদের CORS প্রয়োগ করা প্রয়োজন, তবে তারপরে আপনি কেবল aj .ajax (theimageurl) করুন এবং এটি যুক্তিসঙ্গত কিছু প্রত্যাবর্তন করবে। অন্যথায় (যদি তারা CORS সক্ষম না করে) এটি কাজ করবে না; ইন্টারনেটের সুরক্ষা মডেল এটি অস্বীকার করে। অবশ্যই, যদি না আপনি কোনও ক্রোম প্লাগইন এর ভিতরে থাকেন তবে সেক্ষেত্রে সবকিছুরই অনুমতি রয়েছে - এমনকি উপরের উদাহরণটিও
জ্যারেড ফোর্শিথ

4
আপনার অবশ্যই এটি img.src =পরে রাখা উচিত img.onload =কারণ কয়েকটি ব্রাউজারে যেমন অপেরা, ইভেন্টটি ঘটবে না।
ostapische

1
@ হক্কর একটি মেমরি ফুটো কেবল পুরানো ব্রাউজারগুলিতে দেখা যাবে যা আবর্জনা সংগ্রহকে অবহিত করার জন্য এখনও রেফারেন্স গণনা ব্যবহার করে । আমার উপলব্ধি অনুসারে বিজ্ঞপ্তি রেফারেন্স একটি চিহ্ন এবং সুইপ সেটআপে ফাঁস তৈরি করে না । একবার ফাংশনগুলির স্কোপগুলি getBase64FromImageUrl(url)এবং img.onload = function ()প্রস্থানিত হয়ে গেলে img পৌঁছানো যায় না এবং আবর্জনা সংগ্রহ করা হয়। আইই 6/7 ব্যতীত এবং এটি ঠিক আছে।
humanityANDpeace

59

অনেক পরে আসছেন তবে এখানে উত্তরগুলির কোনওোটাই সম্পূর্ণ সঠিক নয়।

ক্যানভাসে আঁকলে, পাস করা চিত্রটি সঙ্কুচিত হয় + সমস্ত প্রাক গুণিত।
যখন রফতানি করা হয়, এটির সঙ্কুচিত বা ভিন্ন অ্যালগরিদমের সাথে সংকোচিত হয় এবং গুণহীন হয়।

সমস্ত ব্রাউজার এবং ডিভাইসগুলির এই প্রক্রিয়াটিতে বিভিন্ন গোলাকার ত্রুটি ঘটবে
( ক্যানভাস ফিঙ্গারপ্রিন্ট দেখুন )।

সুতরাং যদি কেউ একটি চিত্র ফাইলের একটি বেস 64 সংস্করণ চায় তবে তাদের আবার এটির জন্য অনুরোধ করতে হবে (বেশিরভাগ সময় এটি ক্যাশে থেকে আসবে) তবে এবার ব্লব হিসাবে।

তারপরে আপনি এটির অ্যারেফার বা ডেটা ইউআরএল হিসাবে পড়তে ফাইলআরডার ব্যবহার করতে পারেন ।

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.
এসটিউইলসন

2
@ এসভিউলসন, হ্যাঁ, এই পদ্ধতিটি ক্যানভাসের মতোই একই-উত্স নীতিতেও আবদ্ধ। ক্রস-অরিজিন অনুরোধের ক্ষেত্রে, আপনার স্ক্রিপ্টে ক্রস-অরিজিন অনুরোধগুলির অনুমতি দেওয়ার জন্য আপনাকে হোস্টিং সার্ভারটি কনফিগার করতে হবে।
কাইদো

@ কাইডো তাই যদি চিত্রটি স্ক্রিপ্টের চেয়ে অন্য সার্ভারে থাকে তবে হোস্টিং সার্ভারের ক্রস অরিজিনের অনুরোধগুলি সক্ষম করতে হবে? আপনি যদি img.setAttribute ('ক্রসআরগিন', 'বেনামে') সেট করেন তা কি ত্রুটিটি রোধ করে?
1.21 গিগাওয়াট

1
আরো গবেষণা করার পরে, এটি ইমেজ অনুরোধ অ্যাক্সেস করতে crossOrigin অ্যাট্রিবিউট ব্যবহার করতে পারেন বলে মনে হচ্ছে কিন্তু এটি একটি CORS হেডার মাধ্যমে অ্যাক্সেস দিতে হোস্টিং সার্ভারে আপ sitepoint.com/an-in-depth-look-at-cors । এক্সএমএলএইচটিপিআরকিউয়েস্টের মতো দেখে মনে হচ্ছে যে সার্ভারকে একটি সিওআরএস শিরোলেখের মাধ্যমে চিত্রগুলির মতোই অ্যাক্সেস দিতে হবে তবে xhr.withCredentials কে মিথ্যা (ডিফল্ট) সেট করা ব্যতীত আপনার কোডে কোনও পরিবর্তন প্রয়োজন নেই।
1.21 গিগাওয়াট 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

সম্পাদনা: মন্তব্যে নির্দেশিত হিসাবে এটি কোনও অবজেক্ট ইউআরএল ফিরিয়ে দেবে যা আপনার স্থানীয় সিস্টেমে কোনও প্রকৃত ডেটাআরএল পরিবর্তে কোনও ফাইলকে নির্দেশ করে তাই আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে এটি আপনার প্রয়োজন হতে পারে না।

আনয়ন এবং একটি আসল ডেটা ইউআরএল ব্যবহারের জন্য আপনি নীচের উত্তরগুলি দেখতে পারেন: https://stackoverflow.com/a/50463054/599602


2
URL.revokeObjectURL()এই পদ্ধতিটি ব্যবহার করে আপনার যদি দীর্ঘ চলমান অ্যাপ্লিকেশন থাকে তবে কল করতে ভুলবেন না বা আপনার স্মৃতিশক্তি বিশৃঙ্খল হয়ে পড়ে।
প্রকৌশলী

1
মনোযোগ দিন: ডেটাআরএল (বেস 64 এনকোডেড) অবজেক্ট ইউআরএলটির মতো নয় (ব্লবের রেফারেন্স)
ড্যানিএল

1
অবজেক্ট URL অবশ্যই ডেটা ইউআরএল নয়। এটি সঠিক উত্তর নয়।
ড্যানি লিন

2

শিব / শিম / শ্যাম

যদি আপনার চিত্র (গুলি) ইতিমধ্যে লোড হয় (বা না) তবে এই "সরঞ্জাম" কার্যকর হতে পারে:

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());

জিপিইউ ফিঙ্গারপ্রিন্টিং

আপনি যদি বিটের "নির্ভুলতা" সম্পর্কে উদ্বিগ্ন হন তবে আপনি @ কাইদোর উত্তর দ্বারা সরবরাহিত আপনার প্রয়োজন অনুসারে এই সরঞ্জামটি পরিবর্তন করতে পারেন।


1

onloadলোড করার পরে চিত্র রূপান্তর করতে ইভেন্ট ব্যবহার করুন


-3

এইচটিএমএল 5 এ আরও ভাল ব্যবহার করুন:

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

2
প্রশ্নের উত্তর দেওয়ার সময় আরও সুনির্দিষ্ট হওয়ার চেষ্টা করুন এবং বিস্তারিত ব্যাখ্যা সরবরাহ করুন।
পীযূষ জালানী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.