index.jsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { useEffect, useRef, useState } from "react";
  2. import { areArraysEqual, getImageDataFromPhoto, replaceImageDataColor } from "../../utils/utils";
  3. import { IMAGE_CANVAS_CLASSNAME, PHOTO_HEIGHT, PHOTO_WIDTH } from "../../utils/constants";
  4. // Photos start at 0x2000 with an interval of 0x1000 per photo
  5. const photoStartOffset = 0x2000;
  6. const photoByteLength = 0x1000;
  7. export const ImageFromByteArray = ({ byteArray, photoIndex, imageScale, paletteRGB }) => {
  8. const [imageData, setImageData] = useState(null);
  9. const canvasRef = useRef();
  10. const prevPaletteRef = useRef(paletteRGB);
  11. useEffect(() => {
  12. // Extract one photo data
  13. const photoStart = photoStartOffset + photoByteLength * photoIndex;
  14. const photoEnd = photoStart + photoByteLength;
  15. const photoData = new Uint8Array(byteArray).slice(photoStart, photoEnd);
  16. // Create imageData for canvas from photoData
  17. const newImageData = getImageDataFromPhoto(photoData, paletteRGB);
  18. setImageData(newImageData);
  19. // eslint-disable-next-line react-hooks/exhaustive-deps
  20. }, [byteArray, photoIndex]);
  21. useEffect(() => {
  22. const updateCanvas = () => {
  23. const ctx = canvasRef.current.getContext("2d");
  24. ctx.imageSmoothingEnabled = false;
  25. paletteRGB.forEach((color, index) => {
  26. if (!areArraysEqual(prevPaletteRef.current[index], color)) {
  27. replaceImageDataColor(imageData, index, color);
  28. }
  29. });
  30. ctx.putImageData(imageData, 0, 0);
  31. prevPaletteRef.current = paletteRGB;
  32. };
  33. if (imageData) updateCanvas();
  34. }, [imageData, paletteRGB]);
  35. return (
  36. <canvas
  37. ref={canvasRef}
  38. className={IMAGE_CANVAS_CLASSNAME}
  39. width={PHOTO_WIDTH}
  40. height={PHOTO_HEIGHT}
  41. style={{ width: PHOTO_WIDTH * imageScale, height: PHOTO_HEIGHT * imageScale }}
  42. />
  43. );
  44. };