回答編集履歴

2

Unity 2019で見たテクスチャプレビューを追記

2020/12/01 10:32

投稿

Bongo
Bongo

スコア10811

test CHANGED
@@ -563,3 +563,11 @@
563
563
 
564
564
 
565
565
  ![図4](b67ca52ac550624b9706c1b0100da007.gif)
566
+
567
+
568
+
569
+ ##Unity 2019.4.13f1で見たHeadの様子
570
+
571
+
572
+
573
+ ![図5](752198f42775d10dae379dc77db40a49.gif)

1

ネームスペースを削除、エディター用スクリプトであることを勘案し文面を修正

2020/12/01 10:32

投稿

Bongo
Bongo

スコア10811

test CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
 
21
- だけで`Texture2D`ができあがるという親切お手軽設計でした。そこで凹みTipsさんとはちょっと違ったアプローチですが、まずfo-dicomをインポートした上で下記のようなスクリプトを用意し...
21
+ だけで`Texture2D`ができあがるという親切お手軽設計でした。そこで凹みTipsさんとはちょっと違ったアプローチですが、まずfo-dicomをインポートした上で、プロジェクト内にEditorフォルダを作って下記のようなスクリプトを置き...
22
22
 
23
23
 
24
24
 
@@ -40,31 +40,161 @@
40
40
 
41
41
 
42
42
 
43
- namespace DicomToTexture3D.Editor
43
+ public static class DicomFilesToTexture3D
44
44
 
45
45
  {
46
46
 
47
+ [MenuItem("Utility/DICOM/Create Texture3D from DICOM files")]
48
+
47
- public static class DicomFilesToTexture3D
49
+ private static void CreateTexture3DFromDicomFiles()
48
50
 
49
51
  {
50
52
 
51
- [MenuItem("Utility/DICOM/Create Texture3D from DICOM files")]
52
-
53
- private static void CreateTexture3DFromDicomFiles()
54
-
55
- {
56
-
57
- // まずフォルダ選択ダイアログを出し、DICOMファイル群が収められたフォルダを選んでもらう
58
-
59
- var sourceFolderPath = EditorUtility.OpenFolderPanel(
60
-
61
- "Choose a folder that contains DICOM (*.dcm, *.dic) images",
62
-
63
- string.Empty,
64
-
65
- string.Empty);
66
-
67
- if (string.IsNullOrEmpty(sourceFolderPath))
53
+ // まずフォルダ選択ダイアログを出し、DICOMファイル群が収められたフォルダを選んでもらう
54
+
55
+ var sourceFolderPath = EditorUtility.OpenFolderPanel(
56
+
57
+ "Choose a folder that contains DICOM (*.dcm, *.dic) images",
58
+
59
+ string.Empty,
60
+
61
+ string.Empty);
62
+
63
+ if (string.IsNullOrEmpty(sourceFolderPath))
64
+
65
+ {
66
+
67
+ return;
68
+
69
+ }
70
+
71
+
72
+
73
+ if (!Directory.Exists(sourceFolderPath))
74
+
75
+ {
76
+
77
+ EditorUtility.DisplayDialog("Invalid source", "Choose a valid source folder.", "OK");
78
+
79
+ return;
80
+
81
+ }
82
+
83
+
84
+
85
+ // フォルダ内でファイル名が「.dcm」または「.dic」で終わるものを抜き出してファイルパスを得る
86
+
87
+ var sourceFilePaths = Directory.EnumerateFiles(sourceFolderPath).Where(
88
+
89
+ path => !string.IsNullOrEmpty(path) &&
90
+
91
+ (path.EndsWith(".dcm", StringComparison.OrdinalIgnoreCase) ||
92
+
93
+ path.EndsWith(".dic", StringComparison.OrdinalIgnoreCase)))
94
+
95
+ .OrderBy(path => path).ToArray();
96
+
97
+ var sourceFileCount = sourceFilePaths.Length;
98
+
99
+ if (sourceFileCount <= 0)
100
+
101
+ {
102
+
103
+ EditorUtility.DisplayDialog("Invalid source", "No DICOM images were found.", "OK");
104
+
105
+ return;
106
+
107
+ }
108
+
109
+
110
+
111
+ // ひとまず最初のファイルからDicomImageを作り、できあがるであろうTexture3Dの
112
+
113
+ // サイズ見積もりを提示し、続行するかどうか確認する
114
+
115
+ var firstFilePath = sourceFilePaths.First();
116
+
117
+ DicomImage firstImage;
118
+
119
+ try
120
+
121
+ {
122
+
123
+ firstImage = new DicomImage(firstFilePath);
124
+
125
+ }
126
+
127
+ catch (Exception e)
128
+
129
+ {
130
+
131
+ EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
132
+
133
+ throw;
134
+
135
+ }
136
+
137
+
138
+
139
+ var dimension = new Vector3Int(
140
+
141
+ firstImage.Width,
142
+
143
+ firstImage.Height,
144
+
145
+ firstImage.NumberOfFrames > 1 ? firstImage.NumberOfFrames : sourceFileCount);
146
+
147
+ var resultSize = dimension.x * dimension.y * dimension.z * 4;
148
+
149
+ var resultSizeInKib = resultSize / 1024.0;
150
+
151
+ var resultSizeInMib = resultSizeInKib / 1024.0;
152
+
153
+ var resultSizeInGib = resultSizeInMib / 1024.0;
154
+
155
+ if (!EditorUtility.DisplayDialog(
156
+
157
+ "Confirm Texture3D data size",
158
+
159
+ $"The resulting Texture3D data size will be {resultSize} bytes ({(resultSizeInGib >= 1.0 ? $"{resultSizeInGib:0.##} GB" : resultSizeInMib >= 1.0 ? $"{resultSizeInMib:0.##} MB" : $"{resultSizeInKib:0.##} KB")}). Are you sure want to continue?",
160
+
161
+ "Continue",
162
+
163
+ "Cancel"))
164
+
165
+ {
166
+
167
+ return;
168
+
169
+ }
170
+
171
+
172
+
173
+ Texture3D resultTexture;
174
+
175
+ if (firstImage.NumberOfFrames > 1)
176
+
177
+ {
178
+
179
+ // DICOMは1つのファイルに複数枚のフレームを持つこともできるらしい?
180
+
181
+ // それらフレームが個々の断面を表しているケースもあるのかもしれない...と思い
182
+
183
+ // 先ほど作ったDicomImageに複数のフレームが格納されている場合は、それぞれの
184
+
185
+ // フレームを断面と見なすことにし、もしフォルダ内に他のDICOMファイルが入っていたとしても
186
+
187
+ // それらは無視することにした
188
+
189
+ if ((sourceFileCount > 1) && !EditorUtility.DisplayDialog(
190
+
191
+ "Texture3D will be created from single file",
192
+
193
+ $"{sourceFileCount} DICOM images exist in the folder {Path.GetFileName(sourceFolderPath)}, but file {Path.GetFileName(firstFilePath)} has multiple frames and the Texture3D slices will be taken from this file. All other files will be ignored.",
194
+
195
+ "Continue",
196
+
197
+ "Cancel"))
68
198
 
69
199
  {
70
200
 
@@ -74,460 +204,324 @@
74
204
 
75
205
 
76
206
 
207
+ // まずTexture3Dを生成して...
208
+
209
+ resultTexture = new Texture3D(dimension.x, dimension.y, dimension.z, TextureFormat.RGBA32, false);
210
+
77
- if (!Directory.Exists(sourceFolderPath))
211
+ for (var i = 0; i < firstImage.NumberOfFrames; i++)
78
212
 
79
213
  {
80
214
 
215
+ // 各フレームからUnityImageを生成、さらにそれからTexture2Dを生成して
216
+
217
+ // そのデータをTexture3Dにコピー、最後に用済みのTexture2Dを削除する
218
+
219
+ try
220
+
221
+ {
222
+
223
+ using (var tempImage = firstImage.RenderImage(i))
224
+
225
+ {
226
+
227
+ var tempTexture = tempImage.AsTexture2D();
228
+
229
+ Graphics.CopyTexture(tempTexture, 0, 0, resultTexture, i, 0);
230
+
231
+ Object.DestroyImmediate(tempTexture);
232
+
233
+ }
234
+
235
+ }
236
+
237
+ catch (Exception e)
238
+
239
+ {
240
+
81
- EditorUtility.DisplayDialog("Invalid source", "Choose a valid source folder.", "OK");
241
+ EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
242
+
82
-
243
+ Object.DestroyImmediate(resultTexture);
244
+
83
- return;
245
+ throw;
246
+
247
+ }
84
248
 
85
249
  }
86
250
 
87
-
251
+ }
252
+
88
-
253
+ else
254
+
255
+ {
256
+
257
+ // 最初に調べた1枚目のDicomImageがシングルフレームだったなら、
258
+
89
- // フォルダ内でファイル名が「.dcm」または「.dic」で終わるものを抜き出してファイルパスを得
259
+ // 断面がそれぞれ1ファイルずつに分けられているものと想定す
90
-
91
- var sourceFilePaths = Directory.EnumerateFiles(sourceFolderPath).Where(
260
+
92
-
93
- path => !string.IsNullOrEmpty(path) &&
261
+ // まずTexture3Dを生成して...
94
-
95
- (path.EndsWith(".dcm", StringComparison.OrdinalIgnoreCase) ||
262
+
96
-
97
- path.EndsWith(".dic", StringComparison.OrdinalIgnoreCase)))
263
+ resultTexture = new Texture3D(dimension.x, dimension.y, dimension.z, TextureFormat.RGBA32, false);
98
-
99
- .OrderBy(path => path).ToArray();
264
+
100
-
101
- var sourceFileCount = sourceFilePaths.Length;
265
+ for (var i = 0; i < sourceFilePaths.Length; i++)
102
-
103
- if (sourceFileCount <= 0)
104
266
 
105
267
  {
106
268
 
269
+ // フォルダ内のファイルを1つずつ列挙し、DicomImageを作る
270
+
271
+ var sourceFilePath = sourceFilePaths[i];
272
+
273
+ var sourceFileName = Path.GetFileName(sourceFilePath);
274
+
275
+ DicomImage image;
276
+
277
+ try
278
+
279
+ {
280
+
281
+ image = new DicomImage(sourceFilePath);
282
+
283
+ }
284
+
285
+ catch (Exception e)
286
+
287
+ {
288
+
107
- EditorUtility.DisplayDialog("Invalid source", "No DICOM images were found.", "OK");
289
+ EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
290
+
108
-
291
+ Object.DestroyImmediate(resultTexture);
292
+
293
+ throw;
294
+
295
+ }
296
+
297
+
298
+
299
+ // こちらのケースでは1つのファイルが1つの断面を表していることを前提としており、
300
+
301
+ // もしそこに複数フレームを持つファイルがまぎれ込んでいたら異常事態と見なして中断する
302
+
303
+ if (image.NumberOfFrames > 1)
304
+
305
+ {
306
+
307
+ EditorUtility.DisplayDialog(
308
+
309
+ "Invalid source",
310
+
311
+ $"A multi-frame image {sourceFileName} was found.",
312
+
313
+ "OK");
314
+
315
+ Object.DestroyImmediate(resultTexture);
316
+
109
- return;
317
+ return;
318
+
319
+ }
320
+
321
+
322
+
323
+ // また、すべての断面は幅・高さが同じでないとまずいため、
324
+
325
+ // もしそうでないファイルがまぎれ込んでいた場合も中断する
326
+
327
+ if ((image.Width != dimension.x) || (image.Height != dimension.y))
328
+
329
+ {
330
+
331
+ EditorUtility.DisplayDialog(
332
+
333
+ "Invalid source",
334
+
335
+ $"All images should be the same size. The expected size is ({dimension.x}, {dimension.y}), but the size of image {sourceFileName} is ({image.Width}, {image.Height})",
336
+
337
+ "OK");
338
+
339
+ Object.DestroyImmediate(resultTexture);
340
+
341
+ return;
342
+
343
+ }
344
+
345
+
346
+
347
+ // DicomImageからUnityImageを生成、さらにそれからTexture2Dを生成して
348
+
349
+ // そのデータをTexture3Dにコピー、最後に用済みのTexture2Dを削除する
350
+
351
+ try
352
+
353
+ {
354
+
355
+ using (var tempImage = image.RenderImage())
356
+
357
+ {
358
+
359
+ var tempTexture = tempImage.AsTexture2D();
360
+
361
+ Graphics.CopyTexture(tempTexture, 0, 0, resultTexture, i, 0);
362
+
363
+ Object.DestroyImmediate(tempTexture);
364
+
365
+ }
366
+
367
+ }
368
+
369
+ catch (Exception e)
370
+
371
+ {
372
+
373
+ EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
374
+
375
+ Object.DestroyImmediate(resultTexture);
376
+
377
+ throw;
378
+
379
+ }
110
380
 
111
381
  }
112
382
 
113
-
114
-
115
- // ひとまず最初のファイルからDicomImageを作り、できあがるであろうTexture3Dの
116
-
117
- // ズ見積もり提示し、続行するかどうか確認する
118
-
119
- var firstFilePath = sourceFilePaths.First();
120
-
121
- DicomImage firstImage;
122
-
123
- try
124
-
125
- {
126
-
127
- firstImage = new DicomImage(firstFilePath);
128
-
129
- }
130
-
131
- catch (Exception e)
132
-
133
- {
134
-
135
- EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
136
-
137
- throw;
138
-
139
- }
140
-
141
-
142
-
143
- var dimension = new Vector3Int(
144
-
145
- firstImage.Width,
146
-
147
- firstImage.Height,
148
-
149
- firstImage.NumberOfFrames > 1 ? firstImage.NumberOfFrames : sourceFileCount);
150
-
151
- var resultSize = dimension.x * dimension.y * dimension.z * 4;
152
-
153
- var resultSizeInKib = resultSize / 1024.0;
154
-
155
- var resultSizeInMib = resultSizeInKib / 1024.0;
156
-
157
- var resultSizeInGib = resultSizeInMib / 1024.0;
158
-
159
- if (!EditorUtility.DisplayDialog(
160
-
161
- "Confirm Texture3D data size",
162
-
163
- $"The resulting Texture3D data size will be {resultSize} bytes ({(resultSizeInGib >= 1.0 ? $"{resultSizeInGib:0.##} GB" : resultSizeInMib >= 1.0 ? $"{resultSizeInMib:0.##} MB" : $"{resultSizeInKib:0.##} KB")}). Are you sure want to continue?",
164
-
165
- "Continue",
166
-
167
- "Cancel"))
168
-
169
- {
170
-
171
- return;
172
-
173
- }
174
-
175
-
176
-
177
- Texture3D resultTexture;
178
-
179
- if (firstImage.NumberOfFrames > 1)
180
-
181
- {
182
-
183
- // DICOMは1つのファイルに複数枚のフレームを持つこともできるらしい?
184
-
185
- // それらフレームが個々の断面を表しているケースもあるのかもしれない...と思い
186
-
187
- // 先ほど作ったDicomImageに複数のフレームが格納されている場合は、それぞれの
188
-
189
- // フレームを断面と見なすことにし、もしフォルダ内に他のDICOMファイルが入っていたとしても
190
-
191
- // それらは無視することにした
192
-
193
- if ((sourceFileCount > 1) && !EditorUtility.DisplayDialog(
194
-
195
- "Texture3D will be created from single file",
196
-
197
- $"{sourceFileCount} DICOM images exist in the folder {Path.GetFileName(sourceFolderPath)}, but file {Path.GetFileName(firstFilePath)} has multiple frames and the Texture3D slices will be taken from this file. All other files will be ignored.",
198
-
199
- "Continue",
200
-
201
- "Cancel"))
202
-
203
- {
204
-
205
- return;
206
-
207
- }
208
-
209
-
210
-
211
- // まずTexture3Dを生成して...
212
-
213
- resultTexture = new Texture3D(dimension.x, dimension.y, dimension.z, TextureFormat.RGBA32, false);
214
-
215
- for (var i = 0; i < firstImage.NumberOfFrames; i++)
216
-
217
- {
218
-
219
- // 各フレームからUnityImageを生成、さらにそれからTexture2Dを生成して
220
-
221
- // そのデータをTexture3Dにコピー、最後に用済みのTexture2Dを削除する
222
-
223
- try
224
-
225
- {
226
-
227
- using (var tempImage = firstImage.RenderImage(i))
228
-
229
- {
230
-
231
- var tempTexture = tempImage.AsTexture2D();
232
-
233
- Graphics.CopyTexture(tempTexture, 0, 0, resultTexture, i, 0);
234
-
235
- Object.DestroyImmediate(tempTexture);
236
-
237
- }
238
-
239
- }
240
-
241
- catch (Exception e)
242
-
243
- {
244
-
245
- EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
246
-
247
- Object.DestroyImmediate(resultTexture);
248
-
249
- throw;
250
-
251
- }
252
-
253
- }
254
-
255
- }
256
-
257
- else
258
-
259
- {
260
-
261
- // 最初に調べた1枚目のDicomImageがシングルフレームだったなら、
262
-
263
- // 断面がそれぞれ1ファイルずつに分けられているものと想定する
264
-
265
- // まずTexture3Dを生成して...
266
-
267
- resultTexture = new Texture3D(dimension.x, dimension.y, dimension.z, TextureFormat.RGBA32, false);
268
-
269
- for (var i = 0; i < sourceFilePaths.Length; i++)
270
-
271
- {
272
-
273
- // フォルダ内のファイルを1つずつ列挙し、DicomImageを作る
274
-
275
- var sourceFilePath = sourceFilePaths[i];
276
-
277
- var sourceFileName = Path.GetFileName(sourceFilePath);
278
-
279
- DicomImage image;
280
-
281
- try
282
-
283
- {
284
-
285
- image = new DicomImage(sourceFilePath);
286
-
287
- }
288
-
289
- catch (Exception e)
290
-
291
- {
292
-
293
- EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
294
-
295
- Object.DestroyImmediate(resultTexture);
296
-
297
- throw;
298
-
299
- }
300
-
301
-
302
-
303
- // こちらのケースでは1つのファイルが1つの断面を表していることを前提としており、
304
-
305
- // もしそこに複数フレームを持つファイルがまぎれ込んでいたら異常事態と見なして中断する
306
-
307
- if (image.NumberOfFrames > 1)
308
-
309
- {
310
-
311
- EditorUtility.DisplayDialog(
312
-
313
- "Invalid source",
314
-
315
- $"A multi-frame image {sourceFileName} was found.",
316
-
317
- "OK");
318
-
319
- Object.DestroyImmediate(resultTexture);
320
-
321
- return;
322
-
323
- }
324
-
325
-
326
-
327
- // また、すべての断面は幅・高さが同じでないとまずいため、
328
-
329
- // もしそうでないファイルがまぎれ込んでいた場合も中断する
330
-
331
- if ((image.Width != dimension.x) || (image.Height != dimension.y))
332
-
333
- {
334
-
335
- EditorUtility.DisplayDialog(
336
-
337
- "Invalid source",
338
-
339
- $"All images should be the same size. The expected size is ({dimension.x}, {dimension.y}), but the size of image {sourceFileName} is ({image.Width}, {image.Height})",
340
-
341
- "OK");
342
-
343
- Object.DestroyImmediate(resultTexture);
344
-
345
- return;
346
-
347
- }
348
-
349
-
350
-
351
- // DicomImageからUnityImageを生成、さらにそれからTexture2Dを生成して
352
-
353
- // そのデータをTexture3Dにコピー、最後に用済みのTexture2Dを削除する
354
-
355
- try
356
-
357
- {
358
-
359
- using (var tempImage = image.RenderImage())
360
-
361
- {
362
-
363
- var tempTexture = tempImage.AsTexture2D();
364
-
365
- Graphics.CopyTexture(tempTexture, 0, 0, resultTexture, i, 0);
366
-
367
- Object.DestroyImmediate(tempTexture);
368
-
369
- }
370
-
371
- }
372
-
373
- catch (Exception e)
374
-
375
- {
376
-
377
- EditorUtility.DisplayDialog("Failed", $"{e.GetType()}\n{e.Message}", "OK");
378
-
379
- Object.DestroyImmediate(resultTexture);
380
-
381
- throw;
382
-
383
- }
384
-
385
- }
386
-
387
- }
388
-
389
-
390
-
391
- // セーブダイアログを出してアセットの名前、保存場所を決めてもらい...
392
-
393
- var destinationPath = EditorUtility.SaveFilePanelInProject(
394
-
395
- "Save Texture3D",
396
-
397
- "DICOM Texture",
398
-
399
- "asset",
400
-
401
- "Enter an asset name for the Texture3D.");
402
-
403
- if (string.IsNullOrEmpty(destinationPath))
404
-
405
- {
406
-
407
- Object.DestroyImmediate(resultTexture);
408
-
409
- return;
410
-
411
- }
412
-
413
-
414
-
415
- // できあがったTexture3Dをアセットファイル化して保存する
416
-
417
- AssetDatabase.CreateAsset(resultTexture, destinationPath);
418
-
419
- AssetDatabase.SaveAssets();
420
-
421
- }
422
-
423
-
424
-
425
- // fo-dicomの作るTexture2DがRGBA32フォーマットだったので生成されるTexture3Dのフォーマットも
426
-
427
- // RGBA32にしたものの、今回のようなグレースケールに4チャンネルも使うのはもったいなく思い
428
-
429
- // 生成されたRGBA32のTexture3DからRだけを抜き出してR8フォーマット版を作るメソッドも用意した
430
-
431
- [MenuItem("Utility/DICOM/Convert Texture3D format from RGBA32 to/R8")]
432
-
433
- private static void ConvertToR8()
434
-
435
- {
436
-
437
- ConvertTo(DestinationFormat.R8);
438
-
439
- }
440
-
441
-
442
-
443
- // こちらは抜き出したRをAとして扱わせる
444
-
445
- [MenuItem("Utility/DICOM/Convert Texture3D format from RGBA32 to/Alpha8")]
446
-
447
- private static void ConvertToAlpha8()
448
-
449
- {
450
-
451
- ConvertTo(DestinationFormat.Alpha8);
452
-
453
- }
454
-
455
-
456
-
457
- private static void ConvertTo(DestinationFormat format)
458
-
459
- {
460
-
461
- var targetTexture = Selection.activeObject as Texture3D;
462
-
463
- if ((targetTexture == null) || (targetTexture.format != TextureFormat.RGBA32))
464
-
465
- {
466
-
467
- return;
468
-
469
- }
470
-
471
-
472
-
473
- var newData = targetTexture.GetPixels32(0).Select(c => c.r).ToArray();
474
-
475
- var newTexture = new Texture3D(
476
-
477
- targetTexture.width,
478
-
479
- targetTexture.height,
480
-
481
- targetTexture.depth,
482
-
483
- (TextureFormat)format,
484
-
485
- false);
486
-
487
- newTexture.SetPixelData(newData, 0);
488
-
489
- var destinationPath = EditorUtility.SaveFilePanelInProject(
490
-
491
- "Save Texture3D",
492
-
493
- $"{targetTexture.name} {format}",
494
-
495
- "asset",
496
-
497
- "Enter an asset name for the Texture3D.");
498
-
499
- if (string.IsNullOrEmpty(destinationPath))
500
-
501
- {
502
-
503
- Object.DestroyImmediate(newTexture);
504
-
505
- return;
506
-
507
- }
508
-
509
-
510
-
511
- AssetDatabase.CreateAsset(newTexture, destinationPath);
512
-
513
- AssetDatabase.SaveAssets();
514
-
515
- }
516
-
517
-
518
-
519
- private enum DestinationFormat
520
-
521
- {
522
-
523
- R8 = TextureFormat.R8,
524
-
525
- Alpha8 = TextureFormat.Alpha8
526
-
527
- }
383
+ }
384
+
385
+
386
+
387
+ // セーブダアログてアセットの名前保存場所を決めてもらい...
388
+
389
+ var destinationPath = EditorUtility.SaveFilePanelInProject(
390
+
391
+ "Save Texture3D",
392
+
393
+ "DICOM Texture",
394
+
395
+ "asset",
396
+
397
+ "Enter an asset name for the Texture3D.");
398
+
399
+ if (string.IsNullOrEmpty(destinationPath))
400
+
401
+ {
402
+
403
+ Object.DestroyImmediate(resultTexture);
404
+
405
+ return;
406
+
407
+ }
408
+
409
+
410
+
411
+ // できあがったTexture3Dをアセットファイル化して保存する
412
+
413
+ AssetDatabase.CreateAsset(resultTexture, destinationPath);
414
+
415
+ AssetDatabase.SaveAssets();
528
416
 
529
417
  }
530
418
 
419
+
420
+
421
+ // fo-dicomの作るTexture2DがRGBA32フォーマットだったので生成されるTexture3Dのフォーマットも
422
+
423
+ // RGBA32にしたものの、今回のようなグレースケールに4チャンネルも使うのはもったいなく思い
424
+
425
+ // 生成されたRGBA32のTexture3DからRだけを抜き出してR8フォーマット版を作るメソッドも用意した
426
+
427
+ [MenuItem("Utility/DICOM/Convert Texture3D format from RGBA32 to/R8")]
428
+
429
+ private static void ConvertToR8()
430
+
431
+ {
432
+
433
+ ConvertTo(DestinationFormat.R8);
434
+
435
+ }
436
+
437
+
438
+
439
+ // こちらは抜き出したRをAとして扱わせる
440
+
441
+ [MenuItem("Utility/DICOM/Convert Texture3D format from RGBA32 to/Alpha8")]
442
+
443
+ private static void ConvertToAlpha8()
444
+
445
+ {
446
+
447
+ ConvertTo(DestinationFormat.Alpha8);
448
+
449
+ }
450
+
451
+
452
+
453
+ private static void ConvertTo(DestinationFormat format)
454
+
455
+ {
456
+
457
+ var targetTexture = Selection.activeObject as Texture3D;
458
+
459
+ if ((targetTexture == null) || (targetTexture.format != TextureFormat.RGBA32))
460
+
461
+ {
462
+
463
+ return;
464
+
465
+ }
466
+
467
+
468
+
469
+ var newData = targetTexture.GetPixels32(0).Select(c => c.r).ToArray();
470
+
471
+ var newTexture = new Texture3D(
472
+
473
+ targetTexture.width,
474
+
475
+ targetTexture.height,
476
+
477
+ targetTexture.depth,
478
+
479
+ (TextureFormat)format,
480
+
481
+ false);
482
+
483
+ newTexture.SetPixelData(newData, 0);
484
+
485
+ var destinationPath = EditorUtility.SaveFilePanelInProject(
486
+
487
+ "Save Texture3D",
488
+
489
+ $"{targetTexture.name} {format}",
490
+
491
+ "asset",
492
+
493
+ "Enter an asset name for the Texture3D.");
494
+
495
+ if (string.IsNullOrEmpty(destinationPath))
496
+
497
+ {
498
+
499
+ Object.DestroyImmediate(newTexture);
500
+
501
+ return;
502
+
503
+ }
504
+
505
+
506
+
507
+ AssetDatabase.CreateAsset(newTexture, destinationPath);
508
+
509
+ AssetDatabase.SaveAssets();
510
+
511
+ }
512
+
513
+
514
+
515
+ private enum DestinationFormat
516
+
517
+ {
518
+
519
+ R8 = TextureFormat.R8,
520
+
521
+ Alpha8 = TextureFormat.Alpha8
522
+
523
+ }
524
+
531
525
  }
532
526
 
533
527
  ```