Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Black container when trying to display DICOM image #1795

Open
kelvinleandro opened this issue Feb 2, 2025 · 0 comments
Open

[Bug] Black container when trying to display DICOM image #1795

kelvinleandro opened this issue Feb 2, 2025 · 0 comments

Comments

@kelvinleandro
Copy link

kelvinleandro commented Feb 2, 2025

Describe the Bug

I saw something very similar in issue #1742 but there wasn't a solution. I'm using React + Vite. Currently, the page has a file input, which the wadouri.fileManage.add, imageLoader.loadImage and the viewport.getImageDatata works succesfully when i select the .dcm file, as some logs shows (check the images below). But to display the image, it only shows a black container.
Edit: I also tried to communicate with a Flask server (which will be a crucial part of my project) that, for simplicity, only rotates the received image, and it worked. I was able to save the response image in .dcm format. So, the only problem is with the DICOM visualization.

import { useState, useRef, useEffect } from "react";
import axios from "axios";
import { init as coreInit, RenderingEngine, imageLoader, Types, Enums} from "@cornerstonejs/core";
import {init as dicomImageLoaderInit, wadouri} from "@cornerstonejs/dicom-image-loader";
import { Upload } from "lucide-react";

coreInit();
dicomImageLoaderInit();

const renderingEngineId = "myRenderingEngine";
const viewportId = "dicomViewport";

const HomePage = () => {
  const [image, setImage] = useState<string | null>(null);
  const [dicomFile, setDicomFile] = useState<File | null>(null);
  const imageRef = useRef<HTMLDivElement>(null);
  const renderingEngineRef = useRef<RenderingEngine | null>(null);

  useEffect(() => {
    return () => {
      if (renderingEngineRef.current) {
        renderingEngineRef.current.destroy();
      }
    };
  }, []);

  const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    console.log("Arquivo selecionado:", file);

    setDicomFile(file);

    const imageId = wadouri.fileManager.add(file);
    console.log("ID da imagem:", imageId);
    setImage(imageId);

    try {
      const _image = await imageLoader.loadImage(imageId);
      console.log("Imagem carregada:", _image);
      

      if (!imageRef.current) {
        console.error("imageRef.current é null");
        return;
      }

      if (!renderingEngineRef.current) {
        renderingEngineRef.current = new RenderingEngine(renderingEngineId);
      }

      const renderingEngine = renderingEngineRef.current;

      const viewportInput = {
        viewportId,
        type: Enums.ViewportType.STACK,
        element: imageRef.current,
      }

      renderingEngine.enableElement(viewportInput);
      const viewport = renderingEngine.getViewport(viewportId) as Types.IStackViewport;
      await viewport.setStack([imageId]);
      viewport.render();

      setTimeout(function(){ const metadata = viewport.getImageData(); console.log('Metadados:', metadata);  }, 5000);

    } catch (error) {
      console.error("Erro ao carregar imagem DICOM:", error);
    }
  };

  const sendFileToServer = async () => {
    if (!dicomFile) return;
    const formData = new FormData();
    formData.append("dicom", dicomFile);

    try {
      const response = await axios.post("http://127.0.0.1:5000/upload", formData, {
        headers: { "Content-Type": "multipart/form-data" },
        responseType: "blob", // Expecting a binary response (DICOM file)
      });

      console.log("Resposta do servidor:", response.data);

      const blob = new Blob([response.data], { type: "application/dicom" });
      // const file = new File([blob], "rotated.dcm");
      // Create a downloadable URL
      const downloadUrl = URL.createObjectURL(blob);

      // Create a temporary link and trigger download
      const a = document.createElement("a");
      a.href = downloadUrl;
      a.download = "rotated_image.dcm"; // Filename to save
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);

      // Free memory
      URL.revokeObjectURL(downloadUrl);

    } catch (error) {
      console.error("Erro ao enviar arquivo DICOM:", error);
    }
  };

  return (
    <div className="bg-gray-300 h-screen w-full flex flex-col gap-8 items-center justify-center py-8">
      <div
        onClick={() => document.getElementById("dicom-upload")?.click()}
        className="border-2 border-dashed rounded-lg cursor-pointer border-gray-400 h-[512px] w-[512px] transition-colors"
      >
        {image ? (
          <div className="relative w-full h-full">
            <div ref={imageRef} className="w-[512px] h-[512px]">
              {/* Cornerstone will render the DICOM image here */}
            </div>
            <p className="text-sm text-gray-500 text-center mt-2">
              Clique para mudar a imagem
            </p>
          </div>
        ) : (
          <div className="flex flex-col items-center justify-center gap-2 w-full h-full">
            <Upload size={40} />
            <p className="text-md font-semibold text-center text-gray-500">
              Clique para selecionar imagem DICOM
            </p>
          </div>
        )}
        <input
          id="dicom-upload"
          type="file"
          accept=".dcm"
          className="hidden"
          onChange={handleFileSelect}
        />
      </div>

      <button
        onClick={sendFileToServer}
        disabled={!dicomFile}
        className="py-1 text-lg w-18 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-400"
      >
        Enviar
      </button>

    </div>
  );
};

export default HomePage;

Image

Image

Image

Steps to Reproduce

  1. Create a React + TypeScript project using Vite
  2. Follow the configuration setup outlined in the "Vite" section of the cornerstonejs docs
  3. If you will also configure tailwind, add the following in index.css (layer base is necessary due some bugs like margin and padding that was not working without this):
    @import "tailwindcss";
    
    @layer base {
      *, *::before, *::after {
          box-sizing: border-box;
      }
    
      * {
          margin: 0;
          padding: 0;
      }
    
    }
  4. Install packages:
    • "@cornerstonejs/core": "^2.18.3",
    • "@cornerstonejs/dicom-image-loader": "^2.18.3",
    • "@cornerstonejs/tools": "^2.18.3",
    • "@originjs/vite-plugin-commonjs": "^1.0.3",
    • "dicom-parser": "^1.8.21",
    • "lucide-react": "^0.474.0",
    • "axios": "^1.7.9",

The current behavior

The image container is all black.

The expected behavior

It should display the DICOM image correctly.

OS

Windows 11

Node version

20.11.0

Browser

Chrome 132.0.6834.160

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant