@@ -3,8 +3,11 @@ const glob = require("glob");
3
3
const dicomCodec = require ( "@cornerstonejs/dicom-codec" ) ;
4
4
const staticCS = require ( "@ohif/static-cs-lite" ) ;
5
5
const fs = require ( "fs" ) ;
6
+ const { exec } = require ( "child_process" ) ;
6
7
const decodeImage = require ( "./adapter/decodeImage" ) ;
7
8
const { shouldThumbUseTranscoded } = require ( "./adapter/transcodeImage" ) ;
9
+ const { isVideo } = require ( "../writer/VideoWriter" ) ;
10
+ const Tags = require ( "../dictionary/Tags" ) ;
8
11
9
12
/**
10
13
* Return the middle index of given list
@@ -17,9 +20,13 @@ function getThumbIndex(listThumbs) {
17
20
function internalGenerateThumbnail ( originalImageFrame , dataset , metadata , transferSyntaxUid , doneCallback ) {
18
21
decodeImage ( originalImageFrame , dataset , transferSyntaxUid )
19
22
. then ( ( decodeResult = { } ) => {
20
- const { imageFrame, imageInfo } = decodeResult ;
21
- const pixelData = dicomCodec . getPixelData ( imageFrame , imageInfo , transferSyntaxUid ) ;
22
- staticCS . getRenderedBuffer ( transferSyntaxUid , pixelData , metadata , doneCallback ) ;
23
+ if ( isVideo ( transferSyntaxUid ) ) {
24
+ console . log ( "Video data - no thumbnail generator yet" ) ;
25
+ } else {
26
+ const { imageFrame, imageInfo } = decodeResult ;
27
+ const pixelData = dicomCodec . getPixelData ( imageFrame , imageInfo , transferSyntaxUid ) ;
28
+ staticCS . getRenderedBuffer ( transferSyntaxUid , pixelData , metadata , doneCallback ) ;
29
+ }
23
30
} )
24
31
. catch ( ( error ) => {
25
32
console . log ( `Error while generating thumbnail:: ${ error } ` ) ;
@@ -59,7 +66,7 @@ class ThumbnailService {
59
66
constructor ( ) {
60
67
this . framesThumbnailObj = [ ] ;
61
68
this . favoriteThumbnailObj = { } ;
62
- this . thumbFileName = "thumbnail.jpeg " ;
69
+ this . thumbFileName = "thumbnail" ;
63
70
}
64
71
65
72
/**
@@ -89,16 +96,48 @@ class ThumbnailService {
89
96
this . favoriteThumbnailObj = this . framesThumbnailObj [ favIndex ] ;
90
97
}
91
98
99
+ ffmpeg ( input , output ) {
100
+ exec ( `ffmpeg -i "${ input } " -vf "thumbnail,scale=640:360" -frames:v 1 -f singlejpeg "${ output } "` , ( error , stdout , stderr ) => {
101
+ if ( error ) {
102
+ console . log ( `error: ${ error . message } ` ) ;
103
+ return ;
104
+ }
105
+ if ( stderr ) {
106
+ console . log ( `stderr: ${ stderr } ` ) ;
107
+ return ;
108
+ }
109
+ console . log ( `stdout: ${ stdout } ` ) ;
110
+ } ) ;
111
+ }
112
+
92
113
/**
93
114
* Generates thumbnails for the levels: instances, series, study
94
115
*
95
116
* @param {* } dataSet
96
117
* @param {* } metadata
97
118
* @param {* } callback
98
119
*/
99
- generateThumbnails ( dataSet , metadata , callback ) {
120
+ generateThumbnails ( itemId , dataSet , metadata , callback ) {
100
121
const { imageFrame, id } = this . favoriteThumbnailObj ;
101
122
123
+ // There are various reasons no thumbnails might be generated, so just return
124
+ if ( ! id ) {
125
+ const pixelData = metadata [ Tags . PixelData ] ;
126
+ if ( pixelData ) {
127
+ const { BulkDataURI } = pixelData ;
128
+ if ( BulkDataURI ?. indexOf ( "mp4" ) ) {
129
+ const mp4Path = path . join ( itemId . sopInstanceRootPath , "pixeldata.mp4" ) ;
130
+ const thumbPath = path . join ( itemId . sopInstanceRootPath , "thumbnail" ) ;
131
+ console . log ( "MP4 - converting video format" , mp4Path ) ;
132
+ this . ffmpeg ( mp4Path , thumbPath ) ;
133
+ } else {
134
+ console . log ( "pixelData = " , pixelData , Tags . PixelData ) ;
135
+ }
136
+ } else {
137
+ console . log ( "Series is of other type..." , metadata [ Tags . Modality ] ) ;
138
+ }
139
+ return ;
140
+ }
102
141
internalGenerateThumbnail ( imageFrame , dataSet , metadata , id . transferSyntaxUid , async ( thumbBuffer ) => {
103
142
if ( thumbBuffer ) {
104
143
await callback . thumbWriter ( id . sopInstanceRootPath , this . thumbFileName , thumbBuffer ) ;
0 commit comments