onurzorluer / react-image-file-resizer

Resize Local Images with React 🌄 🌅
MIT License
313 stars 41 forks source link

imageFileResizer is not a function after build #60

Closed ADParris closed 2 years ago

ADParris commented 2 years ago

Describe the bug Works fine in development. I just built the project and am getting "imageFileResizer is not a function". Built with Vite, if that makes any difference.

To Reproduce Steps to reproduce the behavior: Build project with Vitejs.

Expected behavior Well, it would be awesome if it would just work. :)

Desktop (please complete the following information):

ADParris commented 2 years ago

Nevermind. This is most definitely a problem with Vitejs or more specifically whatever build tools they're using. I moved a minimal reproduction over to Create React App and hey what do you know... It built and it works wonderfully. Thanks, again, for this wonderful utility! Have a great day!

ksi9302 commented 2 years ago

Nevermind. This is most definitely a problem with Vitejs or more specifically whatever build tools they're using. I moved a minimal reproduction over to Create React App and hey what do you know... It built and it works wonderfully. Thanks, again, for this wonderful utility! Have a great day!

Hi ADParris, dying to know how you fixed this issue, did you have to do something to vite config..? Much appreciated.

defcom20 commented 1 year ago

yo pude solucionarlo asi:

  1. Copiar todo lo que esta en el index : https://github.com/onurzorluer/react-image-file-resizer/blob/3a0fab44211f985aaf048b4fa71027b7149da90e/src/index.js

  2. la parte donde dice exporta default lo eliminas, luego agregas esto en tu class Resizer, asi:

    static imageFileResizer = (file, maxWidth, maxHeight, compressFormat, quality, rotation, responseUriFunc, outputType, minWidth, minHeight) => { return Resizer.createResizedImage( file, maxWidth, maxHeight, compressFormat, quality, rotation, responseUriFunc, outputType, minWidth, minHeight, ); }

  3. Esto pones fuera de Class Resizer : const resizeFile = (file) => new Promise((resolve) => { Resizer.imageFileResizer(file, 125, 125, "png", 100, 0, (uri) => { resolve(uri) }, "file"); });

    const imageResize = async (file) => { try { const resFile = await resizeFile(file) console.info("todo bien", resFile) return resFile } catch (err) { console.error("esto es un error", err) throw new Error("Return error"); } } export { imageResize }

    1. Asi lo uso: a) import {imageResize} from './utils/imageResize' b) imageResize(event.target.files[0]).then((convertedFile) => { console.log(convertedFile) })
SOUTHYYY commented 1 year ago

yo pude solucionarlo asi:

  1. Copiar todo lo que esta en el index : https://github.com/onurzorluer/react-image-file-resizer/blob/3a0fab44211f985aaf048b4fa71027b7149da90e/src/index.js
  2. la parte donde dice exporta default lo eliminas, luego agregas esto en tu class Resizer, asi: static imageFileResizer = (file, maxWidth, maxHeight, compressFormat, quality, rotation, responseUriFunc, outputType, minWidth, minHeight) => { return Resizer.createResizedImage( file, maxWidth, maxHeight, compressFormat, quality, rotation, responseUriFunc, outputType, minWidth, minHeight, ); }
  3. Esto pones fuera de Class Resizer : const resizeFile = (file) => new Promise((resolve) => { Resizer.imageFileResizer(file, 125, 125, "png", 100, 0, (uri) => { resolve(uri) }, "file"); }); const imageResize = async (file) => { try { const resFile = await resizeFile(file) console.info("todo bien", resFile) return resFile } catch (err) { console.error("esto es un error", err) throw new Error("Return error"); } } export { imageResize }
  4. Asi lo uso: a) import {imageResize} from './utils/imageResize' b) imageResize(event.target.files[0]).then((convertedFile) => { console.log(convertedFile) })

Worked for me, thank you 🔥

jayad23 commented 1 year ago

Thank you. I did implemented it, and worked; and will be filing up a version with TypeScript rather soon.

mikejackowski commented 1 year ago

I'm still having this issue.

serusko commented 1 year ago

@mikejackowski

working TS version

/**
 *
 * @author Onur Zorluer
 *
 */
function changeHeightWidth(
  height: number,
  maxHeight: number,
  width: number,
  maxWidth: number,
  minWidth?: number,
  minHeight?: number,
) {
  if (width > maxWidth) {
    height = Math.round((height * maxWidth) / width);
    width = maxWidth;
  }
  if (height > maxHeight) {
    width = Math.round((width * maxHeight) / height);
    height = maxHeight;
  }
  if (minWidth && width < minWidth) {
    height = Math.round((height * minWidth) / width);
    width = minWidth;
  }
  if (minHeight && height < minHeight) {
    width = Math.round((width * minHeight) / height);
    height = minHeight;
  }
  return { height, width };
}

function resizeAndRotateImage(
  image: HTMLImageElement,
  maxWidth: number,
  maxHeight: number,
  minWidth: undefined | number,
  minHeight: undefined | number,
  compressFormat = 'jpeg',
  quality = 100,
  rotation = 0,
) {
  const qualityDecimal = quality / 100;
  const canvas = document.createElement('canvas');

  let width = image.width;
  let height = image.height;

  const newHeightWidth = changeHeightWidth(height, maxHeight, width, maxWidth, minWidth, minHeight);
  if (rotation && (rotation === 90 || rotation === 270)) {
    canvas.width = newHeightWidth.height;
    canvas.height = newHeightWidth.width;
  } else {
    canvas.width = newHeightWidth.width;
    canvas.height = newHeightWidth.height;
  }

  width = newHeightWidth.width;
  height = newHeightWidth.height;

  const ctx = canvas.getContext('2d');

  if (!ctx) {
    return;
  }
  ctx.fillStyle = 'rgba(0, 0, 0, 0)';
  ctx.fillRect(0, 0, width, height);

  if (ctx.imageSmoothingEnabled && ctx.imageSmoothingQuality) {
    ctx.imageSmoothingQuality = 'high';
  }

  if (rotation) {
    ctx.rotate((rotation * Math.PI) / 180);
    if (rotation === 90) {
      ctx.translate(0, -canvas.width);
    } else if (rotation === 180) {
      ctx.translate(-canvas.width, -canvas.height);
    } else if (rotation === 270) {
      ctx.translate(-canvas.height, 0);
    } else if (rotation === 0 || rotation === 360) {
      ctx.translate(0, 0);
    }
  }
  ctx.drawImage(image, 0, 0, width, height);

  return canvas.toDataURL(`image/${compressFormat}`, qualityDecimal);
}

function b64toByteArrays(b64Data: string) {
  const sliceSize = 512;

  const byteCharacters = atob(
    b64Data.toString().replace(/^data:image\/(png|jpeg|jpg|webp);base64,/, ''),
  );
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
  }
  return byteArrays;
}

function b64toBlob(b64Data: string, contentType: string = 'image/jpeg') {
  const byteArrays = b64toByteArrays(b64Data);
  const blob = new Blob(byteArrays, {
    lastModified: new Date(), // TODO: check problem
    type: contentType,
  } as BlobPropertyBag);
  return blob;
}

function b64toFile(b64Data: string, fileName: string, contentType: string = 'image/jpeg') {
  const byteArrays = b64toByteArrays(b64Data);
  const file = new File(byteArrays, fileName, {
    lastModified: new Date(), // TODO: check problem
    type: contentType,
  } as BlobPropertyBag);
  return file;
}

function createResizedImage(
  file: File,
  maxWidth: number,
  maxHeight: number,
  compressFormat: string,
  quality: number,
  rotation: number,
  responseUriFunc: (blob: string | File | Blob) => void,
  outputType = 'base64',
  minWidth?: number,
  minHeigh?: number,
) {
  const reader = new FileReader();
  if (file) {
    if (file.type && !file.type.includes('image')) {
      throw Error('File Is NOT Image!');
    } else {
      reader.readAsDataURL(file);
      reader.onload = () => {
        const image = new Image();
        image.src = reader.result?.toString() || '';
        image.onload = function () {
          const resizedDataUrl = resizeAndRotateImage(
            image,
            maxWidth,
            maxHeight,
            minWidth,
            minHeigh,
            compressFormat,
            quality,
            rotation,
          );

          if (!resizedDataUrl) {
            return; // TODO: improve typings
          }

          const contentType = `image/${compressFormat}`;
          switch (outputType) {
            case 'blob':
              const blob = b64toBlob(resizedDataUrl, contentType);
              responseUriFunc(blob);
              break;
            case 'base64':
              responseUriFunc(resizedDataUrl);
              break;
            case 'file':
              const fileName = file.name;
              const fileNameWithoutFormat = fileName
                .toString()
                .replace(/(png|jpeg|jpg|webp)$/i, '');
              const newFileName = fileNameWithoutFormat.concat(compressFormat.toString());
              const newFile = b64toFile(resizedDataUrl, newFileName, contentType);
              responseUriFunc(newFile);
              break;
            default:
              responseUriFunc(resizedDataUrl);
          }
        };
      };
      reader.onerror = (error: any) => {
        throw Error(error);
      };
    }
  } else {
    throw Error('File Not Found!');
  }
}

export { createResizedImage };
jorgeluis11 commented 1 year ago

Gracias! This worked great.

romeugodoi commented 1 year ago

@mikejackowski

working TS version

/**
 *
 * @author Onur Zorluer
 *
 */
function changeHeightWidth(
  height: number,
  maxHeight: number,
  width: number,
  maxWidth: number,
  minWidth?: number,
  minHeight?: number,
) {
  if (width > maxWidth) {
    height = Math.round((height * maxWidth) / width);
    width = maxWidth;
  }
  if (height > maxHeight) {
    width = Math.round((width * maxHeight) / height);
    height = maxHeight;
  }
  if (minWidth && width < minWidth) {
    height = Math.round((height * minWidth) / width);
    width = minWidth;
  }
  if (minHeight && height < minHeight) {
    width = Math.round((width * minHeight) / height);
    height = minHeight;
  }
  return { height, width };
}

function resizeAndRotateImage(
  image: HTMLImageElement,
  maxWidth: number,
  maxHeight: number,
  minWidth: undefined | number,
  minHeight: undefined | number,
  compressFormat = 'jpeg',
  quality = 100,
  rotation = 0,
) {
  const qualityDecimal = quality / 100;
  const canvas = document.createElement('canvas');

  let width = image.width;
  let height = image.height;

  const newHeightWidth = changeHeightWidth(height, maxHeight, width, maxWidth, minWidth, minHeight);
  if (rotation && (rotation === 90 || rotation === 270)) {
    canvas.width = newHeightWidth.height;
    canvas.height = newHeightWidth.width;
  } else {
    canvas.width = newHeightWidth.width;
    canvas.height = newHeightWidth.height;
  }

  width = newHeightWidth.width;
  height = newHeightWidth.height;

  const ctx = canvas.getContext('2d');

  if (!ctx) {
    return;
  }
  ctx.fillStyle = 'rgba(0, 0, 0, 0)';
  ctx.fillRect(0, 0, width, height);

  if (ctx.imageSmoothingEnabled && ctx.imageSmoothingQuality) {
    ctx.imageSmoothingQuality = 'high';
  }

  if (rotation) {
    ctx.rotate((rotation * Math.PI) / 180);
    if (rotation === 90) {
      ctx.translate(0, -canvas.width);
    } else if (rotation === 180) {
      ctx.translate(-canvas.width, -canvas.height);
    } else if (rotation === 270) {
      ctx.translate(-canvas.height, 0);
    } else if (rotation === 0 || rotation === 360) {
      ctx.translate(0, 0);
    }
  }
  ctx.drawImage(image, 0, 0, width, height);

  return canvas.toDataURL(`image/${compressFormat}`, qualityDecimal);
}

function b64toByteArrays(b64Data: string) {
  const sliceSize = 512;

  const byteCharacters = atob(
    b64Data.toString().replace(/^data:image\/(png|jpeg|jpg|webp);base64,/, ''),
  );
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
  }
  return byteArrays;
}

function b64toBlob(b64Data: string, contentType: string = 'image/jpeg') {
  const byteArrays = b64toByteArrays(b64Data);
  const blob = new Blob(byteArrays, {
    lastModified: new Date(), // TODO: check problem
    type: contentType,
  } as BlobPropertyBag);
  return blob;
}

function b64toFile(b64Data: string, fileName: string, contentType: string = 'image/jpeg') {
  const byteArrays = b64toByteArrays(b64Data);
  const file = new File(byteArrays, fileName, {
    lastModified: new Date(), // TODO: check problem
    type: contentType,
  } as BlobPropertyBag);
  return file;
}

function createResizedImage(
  file: File,
  maxWidth: number,
  maxHeight: number,
  compressFormat: string,
  quality: number,
  rotation: number,
  responseUriFunc: (blob: string | File | Blob) => void,
  outputType = 'base64',
  minWidth?: number,
  minHeigh?: number,
) {
  const reader = new FileReader();
  if (file) {
    if (file.type && !file.type.includes('image')) {
      throw Error('File Is NOT Image!');
    } else {
      reader.readAsDataURL(file);
      reader.onload = () => {
        const image = new Image();
        image.src = reader.result?.toString() || '';
        image.onload = function () {
          const resizedDataUrl = resizeAndRotateImage(
            image,
            maxWidth,
            maxHeight,
            minWidth,
            minHeigh,
            compressFormat,
            quality,
            rotation,
          );

          if (!resizedDataUrl) {
            return; // TODO: improve typings
          }

          const contentType = `image/${compressFormat}`;
          switch (outputType) {
            case 'blob':
              const blob = b64toBlob(resizedDataUrl, contentType);
              responseUriFunc(blob);
              break;
            case 'base64':
              responseUriFunc(resizedDataUrl);
              break;
            case 'file':
              const fileName = file.name;
              const fileNameWithoutFormat = fileName
                .toString()
                .replace(/(png|jpeg|jpg|webp)$/i, '');
              const newFileName = fileNameWithoutFormat.concat(compressFormat.toString());
              const newFile = b64toFile(resizedDataUrl, newFileName, contentType);
              responseUriFunc(newFile);
              break;
            default:
              responseUriFunc(resizedDataUrl);
          }
        };
      };
      reader.onerror = (error: any) => {
        throw Error(error);
      };
    }
  } else {
    throw Error('File Not Found!');
  }
}

export { createResizedImage };

Thanks man!

cryptoKevinL commented 1 year ago

Is there an NPM version that just works with Vite or are we required to manually pull in this code?

theericharms commented 11 months ago

Thank you the TS version works for me!