expo / expo-pixi

Tools for using pixi.js in Expo
MIT License
304 stars 118 forks source link

FilterImage shows picture sideways #43

Open nisuxyz opened 6 years ago

nisuxyz commented 6 years ago

When replacing an Image component that displays properly with a FilterImage component with same props and settings, it shows the image sideways and stretched. The FilterImage/Image has a flex style within the parent component and is set to resizeMode 'cover'. Attached is what it looks like on the device. First is with Image component, second with FilterImage.

img_0499

img_0498

pieterbeulque commented 5 years ago

I'm running into this too with the most straight-forward code:

const sprite = await ExpoPixi.spriteAsync('file:///…');

@EvanBacon - if you have any clue why this is happening but don't have the time to work on it directly, I can try to help if you give me some pointers.

pieterbeulque commented 5 years ago

@EvanBacon - I figured out why this is happening and how to fix it, but I'm not sure where exactly it should be fixed upstream. It could be in expo-pixi, expo-asset-utils or even in RN's Image… I'm not sure.

How I fix it:

1.a. When capturing from camera

Set exif: true and set a boolean if exif.Orientation === 90.

this.camera.takePictureAsync({
  exif: true,
  onPictureSaved: async (picture) => {
    const { uri, width, height, exif } = picture;
    const shouldCorrectOrientation = exif.Orientation === -90;
  }
});

1.b. When capturing from camera roll

Set exif: true and set a boolean if exif.Orientation === 6

const image = await ImagePicker.launchImageLibraryAsync({ exif: true });
const { uri, width, height, exif } = image;
const shouldCorrectOrientation = exif.Orientation === 6;

2. Load the texture

const texture = Pixi.textureAsync({ uri });
const sprite = Pixi.PIXI.Sprite.from(texture);

3. Swap width & height dimensions if it needs correction

sprite.width = shouldCorrectOrientation ? height : width;
sprite.height = shouldCorrectOrientation ? width : height;

4. Rotate if it needs correction

sprite.rotation = shouldCorrectOrientation ? Math.PI / 2 : 0;

There's probably a lot more edge cases to cover but this worked out for me when snapping pictures and using them as a texture in expo-pixi.

christianjuth commented 5 years ago

I think I am having the same issue. Using this.camera.takePictureAsync() I am able to capture an image. If I load that image into the React Native Image component, the orientation works as expected, but when I use ExpoPixi.FilterImage the image is loading sideways. No matter which way I rotate my device when taking the image, it always seems to come out 90 degrees different than expected. After trying a lot of things I finally decided I was just going to use ImageManipulator to manually rotate the image after capture. Long story short, I realized putting the image through ImageManipulator without any manipulations somehow fixes the orientation. ExpoPixi.FilterImage is now working as expected. I have no idea how this fixed the issue, but it seems to work (only tested on IOS!).

// Image Capture View ------------------

// my camera view captures the image 
// and sends it to the view where filters
// are applied via ExpoPixi.FilterImage
async snap() {
  if (this.camera) {
    let image = await this.camera.takePictureAsync();
    this.props.navigation.navigate('CapturedImage', {
      image: image.uri
    });
  }
};

// Image Processing/Display View ------------------

// after image is recived componentDidMount
// intercepts data and pipes it through ImageManipulator
componentDidMount() {
  this.fixImage(this.props.navigation.state.params.image);
}

async fixImage(image) {
  let data = await ImageManipulator.manipulateAsync(
    image, []
  );
  this.setState({
    image: data
  });
}

// after fixImage has been called
// ExpoPixi.FilterImage renders as exptected
// (ExpoPixi.FilterImage orientation now
// matches React Native Image component) 
render(
  <ExpoPixi.FilterImage
    source={this.state.image}
    resizeMode={'cover'}
    filters={filter}
    style={{
      flex: 1,
      backgroundColor: '#000'
    }}
  />
)