如何使用 expo react native 调整照片大小

Ula*_*ach 3 react-native expo

给定用户设备上照片的 uri(file:// 和 content://),我如何调整照片大小?我正在运行一个托管的博览会应用程序,所以理想情况下我们可以在不分离的情况下做到这一点

Ula*_*ach 12

这可以通过 expo 的ImageManipulator util来完成:

const resizedPhoto = await ImageManipulator.manipulateAsync(
 photo.uri,
 [{ resize: { width: 300 } }], // resize to width of 300 and preserve aspect ratio 
 { compress: 0.7, format: 'jpeg' },
);
Run Code Online (Sandbox Code Playgroud)

注意:我使用的是 expo@v31,最新版本的 @v33 有不同的语法 - 请参考上面的链接


奖励:这是一种确保宽度或高度都不超过最大值的方法

import { ImageManipulator } from 'expo';

enum PhotoDimensions {
  WIDTH = 'width',
  HEIGHT = 'height',
}

const maximalValuesPerDimension = { width: 1000, height: 1000 };
export const resizePhotoToMaxDimensionsAndCompressAsJPEG = async ({ photo }: { photo: { width: number, height: number, uri: string } }) => {
  // 1. define the maximal dimension and the allowed value for it
  const largestDimension = (photo.width > photo.height) ? PhotoDimensions.WIDTH : PhotoDimensions.HEIGHT;
  const initialValueOfLargestDimension = photo[largestDimension];
  const maximalAllowedValueOfLargestDimension = maximalValuesPerDimension[largestDimension];
  const targetValueOfLargestDimension = (initialValueOfLargestDimension > maximalAllowedValueOfLargestDimension) ? maximalAllowedValueOfLargestDimension : initialValueOfLargestDimension;

  // 2. resize the photo w/ that target value for that dimension (keeping the aspect ratio)
  const resizedPhoto = await ImageManipulator.manipulateAsync(
    photo.uri,
    [{ resize: { [largestDimension]: targetValueOfLargestDimension } }],
    { compress: 0.7, format: 'jpeg' },
  );

  // 3. return the resized photo
  return resizedPhoto;
};
Run Code Online (Sandbox Code Playgroud)

以及它的一些测试覆盖率:

import { ImageManipulator } from 'expo';
import { resizePhotoToMaxDimensionsAndCompressAsJPEG } from './resizePhotoToMaxDimensionsAndCompressAsJPEG';

jest.mock('expo', () => ({
  ImageManipulator: {
    manipulateAsync: jest.fn(),
  },
}));
const manipulateAsyncMock = ImageManipulator.manipulateAsync as jest.Mock;

describe('resizePhotoToMaxDimensionsAndCompressAsJPEG', () => {
  beforeEach(() => jest.clearAllMocks());
  it('should not change the dimensions of a photo if neither of its dimensions exceed the largest allowed value', async () => {
    const inputPhoto = { uri: '__TEST_URI__', width: 821, height: 128 };
    await resizePhotoToMaxDimensionsAndCompressAsJPEG({ photo: inputPhoto });
    expect(manipulateAsyncMock).toHaveBeenCalledTimes(1);
    expect(manipulateAsyncMock.mock.calls[0][1][0].resize).toEqual({
      width: 821,
    });
  });
  it('should resize the photo accurately if the width exceeds the largest allowed value', async () => {
    const inputPhoto = { uri: '__TEST_URI__', width: 12000, height: 128 };
    await resizePhotoToMaxDimensionsAndCompressAsJPEG({ photo: inputPhoto });
    expect(manipulateAsyncMock).toHaveBeenCalledTimes(1);
    expect(manipulateAsyncMock.mock.calls[0][1][0].resize).toEqual({
      width: 1000,
    });
  });
  it('should resize the photo accurately if the height exceeds the largest allowed value', async () => {
    const inputPhoto = { uri: '__TEST_URI__', width: 821, height: 12000 };
    await resizePhotoToMaxDimensionsAndCompressAsJPEG({ photo: inputPhoto });
    expect(manipulateAsyncMock).toHaveBeenCalledTimes(1);
    expect(manipulateAsyncMock.mock.calls[0][1][0].resize).toEqual({
      height: 1000,
    });
  });
  it('should compress the photo and convert it into a jpeg', async () => {
    const inputPhoto = { uri: '__TEST_URI__', width: 821, height: 12000 };
    await resizePhotoToMaxDimensionsAndCompressAsJPEG({ photo: inputPhoto });
    expect(manipulateAsyncMock).toHaveBeenCalledTimes(1);
    expect(manipulateAsyncMock.mock.calls[0][2]).toEqual({
      compress: expect.any(Number),
      format: 'jpeg',
    });
  });
});
Run Code Online (Sandbox Code Playgroud)