Various registrations have size restrictions on photos. In view of this situation, I searched online and pieced together the following code, which is used to change the 1-inch photo into a 2-inch photo, and at the same time change the DPI to 300. Of course, you can also change it according to your own requirements. Situation modification code:
HTML
<input type="file" id="input" accept="image/*"> <div style="display: grid;grid-template-columns: 1fr 5px 1fr;"> <div> <p>before fixing:</p> <img id="before-image" src="" style="display: block; max-width:100%;" > </div> <div></div> <div> <p>After modification (click on the image to download):</p> <a href="javascript:;" download><img id="after-image" src="" style="display: block;"></a> </div> </div>
JS
<script type="text/javascript"> const after_image = document.getElementById('before-image'); document.getElementById('input').addEventListener('change', (e) => {<!-- --> const reader = new FileReader(); reader.readAsDataURL(e.target.files[0]); reader.onload = (e) => {<!-- --> b64 = e.target.result; after_image.src = b64; //Set the target image size var target_width = 413; var target_height = 626; //Calculate the width and height ratio of the target image var target_wh_scale = target_width / target_height; //Define an Image object var bitmap = new Image(); bitmap.src = b64; bitmap.onload = function () {<!-- --> // var cut_width = 0; var cut_height = 0; // var bitmap_wh_scale = bitmap.width / bitmap.height; if (bitmap_wh_scale > target_wh_scale) {<!-- --> cut_width = bitmap.width - bitmap.width / (bitmap_wh_scale / target_wh_scale); }//Crop width else if (bitmap_wh_scale < target_wh_scale) {<!-- --> cut_height = bitmap.height - bitmap.height * (bitmap_wh_scale / target_wh_scale); } else {<!-- --> Console.log("The proportions are consistent without cropping"); } console.log("Picture cropping width:" + cut_width + " px"); console.log("Picture cropping height:" + cut_height + " px"); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = target_width; canvas.height = target_height; ctx.drawImage(this, cut_width / 2, cut_height / 2, bitmap.width - cut_width, bitmap.height - cut_height, 0, 0, target_width, target_height); var after_img = document.getElementById('after-image'); after_img.src = canvas.toDataURL('image/jpg'); var dataUrl = canvas.toDataURL('image/jpeg', 0.9); //Modify DPI to 300 downloadBase64Img(after_img.parentElement, changeDpiDataUrl(dataUrl, 300), "t.jpg"); } }; }) function downloadBase64Img(a, base64URL, fileName) {<!-- --> //Set the download attribute of the a tag to the name of the file to be downloaded a.download = fileName || 'image'; //Create a Blob object and get the MIME type of base64 data const mimeType = base64URL.match(/:(.*?);/)[1]; //Convert base64 data to byte array const byteCharacters = atob(base64URL.split(',')[1]); const byteNumbers = new Array(byteCharacters.length); // Fill the byte array into Uint8Array for (let i = 0; i < byteCharacters.length; i + + ) {<!-- --> byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); //Create Blob object const blob = new Blob([byteArray], {<!-- --> type: mimeType }); //Assign the URL of the Blob object to the href attribute of the a tag a.href = URL.createObjectURL(blob); } function changeDpiDataUrl(base64Image, dpi) {<!-- --> const PNG = 'image/png'; const JPEG = 'image/jpeg'; const dataSplitted = base64Image.split(','); const format = dataSplitted[0]; const body = dataSplitted[1]; let type; let headerLength; let overwritepHYs = false; if (format.indexOf(PNG) !== -1) {<!-- --> type = PNG; const b64Index = detectPhysChunkFromDataUrl(body); // 28 bytes in dataUrl are 21bytes, length of phys chunk with everything inside. if (b64Index >= 0) {<!-- --> headerLength = Math.ceil((b64Index + 28) / 3) * 4; overwritepHYs = true; } else {<!-- --> headerLength = 33 / 3 * 4; } } if (format.indexOf(JPEG) !== -1) {<!-- --> type = JPEG; headerLength = 18 / 3 * 4; } // 33 bytes are ok for pngs and jpegs // to contain the information. const stringHeader = body.substring(0, headerLength); const restOfData = body.substring(headerLength); const headerBytes = atob(stringHeader); const dataArray = new Uint8Array(headerBytes.length); for (let i = 0; i < dataArray.length; i + + ) {<!-- --> dataArray[i] = headerBytes.charCodeAt(i); } const finalArray = changeDpiOnArray(dataArray, dpi, type, overwritepHYs); const base64Header = btoa(String.fromCharCode(...finalArray)); return [format, ',', base64Header, restOfData].join(''); } function changeDpiOnArray(dataArray, dpi, format, overwritepHYs) {<!-- --> const PNG = 'image/png'; const JPEG = 'image/jpeg'; if (format === JPEG) {<!-- --> dataArray[13] = 1; // 1 pixel per inch or 2 pixel per cm dataArray[14] = dpi >> 8; // dpiX high byte dataArray[15] = dpi & 0xff; // dpiX low byte dataArray[16] = dpi >> 8; // dpiY high byte dataArray[17] = dpi & amp; 0xff; // dpiY low byte return dataArray; } if (format === PNG) {<!-- --> const physChunk = new Uint8Array(13); // chunk header pHYs // 9 bytes of data // 4 bytes of crc // this multiplication is because the standard is dpi per meter. const _P = 'p'.charCodeAt(0); const _H = 'H'.charCodeAt(0); const _Y = 'Y'.charCodeAt(0); const _S = 's'.charCodeAt(0); dpi *= 39.3701; physChunk[0] = _P; physChunk[1] = _H; physChunk[2] = _Y; physChunk[3] = _S; physChunk[4] = dpi >>> 24; // dpiX highest byte physChunk[5] = dpi >>> 16; // dpiX veryhigh byte physChunk[6] = dpi >>> 8; // dpiX high byte physChunk[7] = dpi & amp; 0xff; // dpiX low byte physChunk[8] = physChunk[4]; // dpiY highest byte physChunk[9] = physChunk[5]; // dpiY veryhigh byte physChunk[10] = physChunk[6]; // dpiY high byte physChunk[11] = physChunk[7]; // dpiY low byte physChunk[12] = 1; // dot per meter.... const crc = calcCrc(physChunk); const crcChunk = new Uint8Array(4); crcChunk[0] = crc >>> 24; crcChunk[1] = crc >>> 16; crcChunk[2] = crc >>> 8; crcChunk[3] = crc & 0xff; if (overwritepHYs) {<!-- --> const startingIndex = searchStartOfPhys(dataArray); dataArray.set(physChunk, startingIndex); dataArray.set(crcChunk, startingIndex + 13); return dataArray; } else {<!-- --> // i need to give back an array of data that is divisible by 3 so that // dataurl encoding gives me integers, for luck this chunk is 17 + 4 = 21 // if it was we could add a text chunk contaning some info, untill desired // length is met. // chunk structur 4 bytes for length is 9 const chunkLength = new Uint8Array(4); chunkLength[0] = 0; chunkLength[1] = 0; chunkLength[2] = 0; chunkLength[3] = 9; const finalHeader = new Uint8Array(54); finalHeader.set(dataArray, 0); finalHeader.set(chunkLength, 33); finalHeader.set(physChunk, 37); finalHeader.set(crcChunk, 50); return finalHeader; } } } </script>
The two functions changeDpiDataUrl()
and changeDpiOnArray()
in the above code come from the open source project changeDPI.