質問編集履歴

2

タイトルを変更

2017/04/14 08:55

投稿

dylan
dylan

スコア26

test CHANGED
@@ -1 +1 @@
1
- UWP InkCanvas アニメーションGIFの書き込みについて
1
+ UWP InkCanvas アニメーションGIFのバイナリ書き込みをすると背景が黒くなることについて
test CHANGED
File without changes

1

コードを追加

2017/04/14 08:55

投稿

dylan
dylan

スコア26

test CHANGED
File without changes
test CHANGED
@@ -4,338 +4,524 @@
4
4
 
5
5
  どなたかご教授ください。お願いします。
6
6
 
7
-
8
-
9
7
  以下ファイル書き込みコードの一部です。
10
8
 
11
9
  ```C#
12
10
 
13
11
  //アニメーションGif(isfメタデータの)を書き出す
14
12
 
15
- public async void Write(StorageFile file, UInt16 delayTime)
13
+ public async void Write(StorageFile file, UInt16 delayTime)
14
+
15
+ {
16
+
17
+ IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);
18
+
19
+ MemoryStream memoryStream = new MemoryStream();
20
+
21
+ BinaryWriter binaryWriter = new BinaryWriter(fileStream.AsStream());
22
+
23
+ bool hasGlobalColorTable = false; //グローバルカラーテーブルがあるか
24
+
25
+ int colorTableSize = 0; //カラーテーブルのサイズ
26
+
27
+
28
+
29
+ //アプリケーションで指定したファイルのリアルタイム更新を遅延
30
+
31
+ //Prevent updates to the file until updates are
32
+
33
+ //finalized with call to CompleteUpdatesAsync.
34
+
35
+ CachedFileManager.DeferUpdates(file);
36
+
37
+
38
+
39
+ for (int i = 0; i < sketchBook.Count; i++)
40
+
41
+ {
42
+
43
+ //InkCanvasからすべてのstrokeを取得
44
+
45
+ IReadOnlyList<InkStroke> strokes = sketchBook[i].InkPresenter.StrokeContainer.GetStrokes();
46
+
47
+
48
+
49
+ if (strokes.Count >= 0)
16
50
 
17
51
  {
18
52
 
19
- IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);
20
-
21
- MemoryStream memoryStream = new MemoryStream();
53
+ //メモリに保存
22
-
54
+
23
- BinaryWriter binaryWriter = new BinaryWriter(fileStream.AsStream());
55
+ await sketchBook[i].InkPresenter.StrokeContainer.SaveAsync(memoryStream.AsOutputStream());
24
-
25
- bool hasGlobalColorTable = false; //グローバルカラーテーブルがあるか
56
+
26
-
27
- int colorTableSize = 0; //カラーテーブルのサイズ
57
+
28
-
29
-
30
-
58
+
31
- //アプケーションで指定したファイルリアルタイム更新遅延
59
+ //メモリの位置0にする
32
-
33
- //Prevent updates to the file until updates are
60
+
34
-
35
- //finalized with call to CompleteUpdatesAsync.
36
-
37
- CachedFileManager.DeferUpdates(file);
61
+ memoryStream.Position = 0;
38
-
39
-
40
-
62
+
63
+
64
+
41
- for (int i = 0; i < sketchBook.Count; i++)
65
+ if (i == 0)
42
66
 
43
67
  {
44
68
 
69
+ //Header読み込み、書き込み
70
+
71
+ //GIF89a
72
+
73
+ byte[] header = ReadBytes(memoryStream, 6);
74
+
75
+ binaryWriter.Write(header);
76
+
77
+
78
+
45
- //InkCanvasからすべてのstrokeを取得
79
+ //Logical Screen Descriptor読み込み
80
+
46
-
81
+ byte[] screenDescriptor = ReadBytes(memoryStream, 7);
82
+
83
+
84
+
85
+ //Gif画像全体のサイズを設定
86
+
87
+ UInt16 width, height;
88
+
89
+ width = (UInt16)sketchBook[i].ActualWidth;
90
+
91
+ height = (UInt16)sketchBook[i].ActualHeight;
92
+
93
+ byte[] widthBytes = BitConverter.GetBytes(width);
94
+
47
- IReadOnlyList<InkStroke> strokes = sketchBook[i].InkPresenter.StrokeContainer.GetStrokes();
95
+ byte[] heightBytes = BitConverter.GetBytes(height);
96
+
48
-
97
+ screenDescriptor[0] = widthBytes[0];
98
+
49
-
99
+ screenDescriptor[1] = widthBytes[1];
100
+
50
-
101
+ screenDescriptor[2] = heightBytes[0];
102
+
103
+ screenDescriptor[3] = heightBytes[1];
104
+
105
+
106
+
107
+ //背景色
108
+
109
+ screenDescriptor[5] = 0xFF;
110
+
111
+
112
+
113
+ //Global Color Tableがあるか
114
+
51
- if (strokes.Count >= 0)
115
+ if ((screenDescriptor[4] & 0x80) != 0)
52
116
 
53
117
  {
54
118
 
55
- //メモリに保存
56
-
57
- await sketchBook[i].InkPresenter.StrokeContainer.SaveAsync(memoryStream.AsOutputStream());
58
-
59
-
60
-
61
- //メモリの位置を0にする
62
-
63
- memoryStream.Position = 0;
64
-
65
-
66
-
67
- if (i == 0)
68
-
69
- {
70
-
71
- //Header読み込み、書き込み
72
-
73
- //GIF89a
74
-
75
- byte[] header = ReadBytes(memoryStream, 6);
76
-
77
- binaryWriter.Write(header);
78
-
79
-
80
-
81
- //Logical Screen Descriptor読み込み
82
-
83
- byte[] screenDescriptor = ReadBytes(memoryStream, 7);
84
-
85
-
86
-
87
- //Gif画像全体のサイズを設定
88
-
89
- UInt16 width, height;
90
-
91
- width = (UInt16)sketchBook[i].ActualWidth;
92
-
93
- height = (UInt16)sketchBook[i].ActualHeight;
94
-
95
- byte[] widthBytes = BitConverter.GetBytes(width);
96
-
97
- byte[] heightBytes = BitConverter.GetBytes(height);
98
-
99
- screenDescriptor[0] = widthBytes[0];
100
-
101
- screenDescriptor[1] = widthBytes[1];
102
-
103
- screenDescriptor[2] = heightBytes[0];
104
-
105
- screenDescriptor[3] = heightBytes[1];
106
-
107
-
108
-
109
- //背景色
110
-
111
- screenDescriptor[5] = 0xFF;
112
-
113
-
114
-
115
- //Global Color Tableがあるか
116
-
117
- if ((screenDescriptor[4] & 0x80) != 0)
118
-
119
- {
120
-
121
- //Color Tableのサイズを取得
119
+ //Color Tableのサイズを取得
122
-
120
+
123
- colorTableSize = screenDescriptor[4] & 0x07;
121
+ colorTableSize = screenDescriptor[4] & 0x07;
124
-
122
+
125
- hasGlobalColorTable = true;
123
+ hasGlobalColorTable = true;
126
-
127
- }
128
-
129
- else
130
-
131
- {
132
-
133
- hasGlobalColorTable = false;
134
-
135
- }
136
-
137
-
138
-
139
- //Global Color Tableを使わない
140
-
141
- //広域配色表フラグと広域配色表の寸法を消す
142
-
143
- screenDescriptor[4] = (byte)(screenDescriptor[4] & 0x78);
144
-
145
-
146
-
147
- //Logical Screen Descriptor書き込み
148
-
149
- binaryWriter.Write(screenDescriptor);
150
-
151
-
152
-
153
- //Application Extensionを追加
154
-
155
- binaryWriter.Write(GetApplicationExtension(0));
156
-
157
- }
158
-
159
- else
160
-
161
- {
162
-
163
- //HeaderとLogical Screen Descriptorをスキップ
164
-
165
- memoryStream.Position = 6 + 7;
166
-
167
- }
168
-
169
-
170
-
171
- //Graphics Control Extension読み込み、書き込み
172
-
173
- byte[] graphicsControlExtension = ReadBytes(memoryStream, 8);
174
-
175
- binaryWriter.Write(GetGraphicControlExtension(delayTime));
176
-
177
-
178
-
179
- byte[] colorTable = null;
180
-
181
- if (hasGlobalColorTable)
182
-
183
- {
184
-
185
- //Color Tableを取得、3はRGB
186
-
187
- colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3);
188
-
189
- }
190
-
191
-
192
-
193
- //Image Descriptor読み込み
194
-
195
- byte[] imageDescriptor = ReadBytes(memoryStream, 10);
196
-
197
-
198
-
199
- //位置の設定
200
-
201
- byte[] xBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.X);
202
-
203
- byte[] yBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.Y);
204
-
205
- imageDescriptor[1] = xBytes[0];
206
-
207
- imageDescriptor[2] = xBytes[1];
208
-
209
- imageDescriptor[3] = yBytes[0];
210
-
211
- imageDescriptor[4] = yBytes[1];
212
-
213
-
214
-
215
- if (!hasGlobalColorTable)
216
-
217
- {
218
-
219
- //Local Color Tableを持っているか
220
-
221
- if ((imageDescriptor[9] & 0x80) == 0)
222
-
223
- throw new Exception("Not found local color table.");
224
-
225
-
226
-
227
- //Color Tableのサイズを取得
228
-
229
- colorTableSize = imageDescriptor[9] & 7;
230
-
231
-
232
-
233
- //Color Tableを取得
234
-
235
- colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3);
236
-
237
- }
238
-
239
-
240
-
241
- //狭域配色表フラグ (Local Color Table Flag)と狭域配色表の寸法を追加
242
-
243
- imageDescriptor[9] = (byte)(imageDescriptor[9] | 0x80 | colorTableSize);
244
-
245
-
246
-
247
- //Image Descriptor書き込み
248
-
249
- binaryWriter.Write(imageDescriptor);
250
-
251
-
252
-
253
- //Local Color Table書き込み
254
-
255
- binaryWriter.Write(colorTable);
256
-
257
-
258
-
259
- //Image Data読み込み、書き込み(終了部0x3Bは書き込まない)
260
-
261
- byte[] imageDataBytes = ReadBytes(memoryStream, (int)(memoryStream.Length - memoryStream.Position - 1));
262
-
263
- binaryWriter.Write(imageDataBytes);
264
-
265
-
266
-
267
- //0x3Bを読み飛ばし
268
-
269
- byte[] end = ReadBytes(memoryStream, 1);
270
-
271
-
272
-
273
- if (i == sketchBook.Count - 1)
274
-
275
- {
276
-
277
- //終了部(Trailer)書き込み
278
-
279
- binaryWriter.Write((byte)0x3B);
280
-
281
- }
282
-
283
-
284
-
285
- //MemoryStreamをリセット
286
-
287
- memoryStream.SetLength(0);
288
124
 
289
125
  }
290
126
 
127
+ else
128
+
129
+ {
130
+
131
+ hasGlobalColorTable = false;
132
+
133
+ }
134
+
135
+
136
+
137
+ //Global Color Tableを使わない
138
+
139
+ //広域配色表フラグと広域配色表の寸法を消す
140
+
141
+ screenDescriptor[4] = (byte)(screenDescriptor[4] & 0x78);
142
+
143
+
144
+
145
+ //Logical Screen Descriptor書き込み
146
+
147
+ binaryWriter.Write(screenDescriptor);
148
+
149
+
150
+
151
+ //Application Extensionを追加
152
+
153
+ binaryWriter.Write(GetApplicationExtension(0));
154
+
291
155
  }
292
156
 
293
-
294
-
295
- //指定したファイルの更新を開始
296
-
297
- //Finalize write so other apps can update file.
298
-
299
- Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
300
-
301
-
302
-
303
- //ファイルが保存されたとき
157
+ else
304
-
305
- if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
306
158
 
307
159
  {
308
160
 
161
+ //HeaderとLogical Screen Descriptorをスキップ
162
+
163
+ memoryStream.Position = 6 + 7;
164
+
309
165
  }
310
166
 
167
+
168
+
311
- //ファイルが正常に保存されなかったと
169
+ //Graphics Control Extension読み込み、書込み
170
+
312
-
171
+ byte[] graphicsControlExtension = ReadBytes(memoryStream, 8);
172
+
173
+ binaryWriter.Write(GetGraphicControlExtension(delayTime));
174
+
175
+
176
+
313
- else
177
+ byte[] colorTable = null;
178
+
179
+ if (hasGlobalColorTable)
314
180
 
315
181
  {
316
182
 
183
+ //Color Tableを取得、3はRGB
184
+
185
+ colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3);
186
+
317
187
  }
318
188
 
319
189
 
320
190
 
191
+ //Image Descriptor読み込み
192
+
193
+ byte[] imageDescriptor = ReadBytes(memoryStream, 10);
194
+
195
+
196
+
197
+ //位置の設定
198
+
199
+ byte[] xBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.X);
200
+
201
+ byte[] yBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.Y);
202
+
203
+ imageDescriptor[1] = xBytes[0];
204
+
205
+ imageDescriptor[2] = xBytes[1];
206
+
207
+ imageDescriptor[3] = yBytes[0];
208
+
209
+ imageDescriptor[4] = yBytes[1];
210
+
211
+
212
+
213
+ if (!hasGlobalColorTable)
214
+
215
+ {
216
+
217
+ //Local Color Tableを持っているか
218
+
219
+ if ((imageDescriptor[9] & 0x80) == 0)
220
+
221
+ throw new Exception("Not found local color table.");
222
+
223
+
224
+
225
+ //Color Tableのサイズを取得
226
+
227
+ colorTableSize = imageDescriptor[9] & 7;
228
+
229
+
230
+
231
+ //Color Tableを取得
232
+
233
+ colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3);
234
+
235
+ }
236
+
237
+
238
+
239
+ //狭域配色表フラグ (Local Color Table Flag)と狭域配色表の寸法を追加
240
+
241
+ imageDescriptor[9] = (byte)(imageDescriptor[9] | 0x80 | colorTableSize);
242
+
243
+
244
+
245
+ //Image Descriptor書き込み
246
+
321
- await memoryStream.FlushAsync();
247
+ binaryWriter.Write(imageDescriptor);
248
+
249
+
250
+
322
-
251
+ //Local Color Table書き込み
252
+
323
-
253
+ binaryWriter.Write(colorTable);
254
+
255
+
256
+
324
-
257
+ //Image Data読み込み、書き込み(終了部0x3Bは書き込まない)
258
+
259
+ byte[] imageDataBytes = ReadBytes(memoryStream, (int)(memoryStream.Length - memoryStream.Position - 1));
260
+
325
- await fileStream.FlushAsync();
261
+ binaryWriter.Write(imageDataBytes);
262
+
263
+
264
+
326
-
265
+ //0x3Bを読み飛ばし
266
+
327
-
267
+ byte[] end = ReadBytes(memoryStream, 1);
268
+
269
+
270
+
328
-
271
+ if (i == sketchBook.Count - 1)
272
+
273
+ {
274
+
275
+ //終了部(Trailer)書き込み
276
+
277
+ binaryWriter.Write((byte)0x3B);
278
+
279
+ }
280
+
281
+
282
+
283
+ //MemoryStreamをリセット
284
+
329
- memoryStream.Dispose();
285
+ memoryStream.SetLength(0);
330
-
331
-
332
-
333
- binaryWriter.Dispose();
334
-
335
-
336
-
337
- fileStream.Dispose();
338
286
 
339
287
  }
340
288
 
289
+ }
290
+
291
+
292
+
293
+ //指定したファイルの更新を開始
294
+
295
+ //Finalize write so other apps can update file.
296
+
297
+ Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
298
+
299
+
300
+
301
+ //ファイルが保存されたとき
302
+
303
+ if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
304
+
305
+ {
306
+
307
+ }
308
+
309
+ //ファイルが正常に保存されなかったとき
310
+
311
+ else
312
+
313
+ {
314
+
315
+ }
316
+
317
+
318
+
319
+ await memoryStream.FlushAsync();
320
+
321
+
322
+
323
+ await fileStream.FlushAsync();
324
+
325
+
326
+
327
+ memoryStream.Dispose();
328
+
329
+
330
+
331
+ binaryWriter.Dispose();
332
+
333
+
334
+
335
+ fileStream.Dispose();
336
+
337
+ }
338
+
339
+
340
+
341
+ //MemoryStreamの現在の位置から指定されたサイズのバイト配列を読み込む
342
+
343
+ //memoryStream : 読み取るMemoryStream
344
+
345
+ //count : 読み取るバイトのサイズ
346
+
347
+ //戻り値 : 読み取れたバイト配列
348
+
349
+ static byte[] ReadBytes(MemoryStream memoryStream, int count)
350
+
351
+ {
352
+
353
+ byte[] bytes = new byte[count];
354
+
355
+ memoryStream.Read(bytes, 0, count);
356
+
357
+ return bytes;
358
+
359
+ }
360
+
361
+
362
+
363
+ //Netscape Application Extensionブロックを返す
364
+
365
+ //loopCount : 繰り返す回数、0で無限
366
+
367
+ //戻り値 : Netscape Application Extensionブロックのbyte配列
368
+
369
+ static byte[] GetApplicationExtension(UInt16 loopCount)
370
+
371
+ {
372
+
373
+ byte[] block = new byte[19];
374
+
375
+
376
+
377
+ //拡張導入符(Extension Introducer)
378
+
379
+ block[0] = 0x21;
380
+
381
+
382
+
383
+ //アプリケーション拡張ラベル(Application Extension Label)
384
+
385
+ block[1] = 0xFF;
386
+
387
+
388
+
389
+ //ブロック寸法(Block Size)
390
+
391
+ block[2] = 0x0B;
392
+
393
+
394
+
395
+ //アプリケーション識別名(Application Identifier)
396
+
397
+ block[3] = (byte)'N';
398
+
399
+ block[4] = (byte)'E';
400
+
401
+ block[5] = (byte)'T';
402
+
403
+ block[6] = (byte)'S';
404
+
405
+ block[7] = (byte)'C';
406
+
407
+ block[8] = (byte)'A';
408
+
409
+ block[9] = (byte)'P';
410
+
411
+ block[10] = (byte)'E';
412
+
413
+
414
+
415
+ //アプリケーション確証符号(Application Authentication Code)
416
+
417
+ block[11] = (byte)'2';
418
+
419
+ block[12] = (byte)'.';
420
+
421
+ block[13] = (byte)'0';
422
+
423
+
424
+
425
+ //データ副ブロック寸法(Data Sub-block Size)
426
+
427
+ block[14] = 0x03;
428
+
429
+
430
+
431
+ //詰め込み欄[ネットスケープ拡張コード(Netscape Extension Code)]
432
+
433
+ block[15] = 0x01;
434
+
435
+
436
+
437
+ //繰り返し回数(Loop Count)
438
+
439
+ byte[] loopCountBytes = BitConverter.GetBytes(loopCount);
440
+
441
+ block[16] = loopCountBytes[0];
442
+
443
+ block[17] = loopCountBytes[1];
444
+
445
+
446
+
447
+ //ブロック終了符(Block Terminator)
448
+
449
+ block[18] = (byte)0x00;
450
+
451
+
452
+
453
+ return block;
454
+
455
+ }
456
+
457
+
458
+
459
+ //Graphic Control Extensionブロックを返す
460
+
461
+ //delayTime : 遅延時間(100分の1秒単位)
462
+
463
+ //戻り値 : Graphic Control Extensionブロックのbyte配列
464
+
465
+ static byte[] GetGraphicControlExtension(UInt16 delayTime)
466
+
467
+ {
468
+
469
+ byte[] block = new byte[8];
470
+
471
+
472
+
473
+ //拡張導入符(Extension Introducer)
474
+
475
+ block[0] = 0x21;
476
+
477
+
478
+
479
+ //グラフィック制御ラベル(Graphic Control Label)
480
+
481
+ block[1] = 0xF9;
482
+
483
+
484
+
485
+ //ブロック寸法(Block Size, Byte Size)
486
+
487
+ block[2] = 0x04;
488
+
489
+
490
+
491
+ //詰め込み欄(Packed Field)
492
+
493
+ //透過色指標を使う時は+1
494
+
495
+ //消去方法 : そのまま残す+4、背景色でつぶす+8、直前の画像に戻す+12
496
+
497
+ block[3] = 0x00 + 8;
498
+
499
+
500
+
501
+ //遅延時間(Delay Time)
502
+
503
+ byte[] delayTimeBytes = BitConverter.GetBytes(delayTime);
504
+
505
+ block[4] = delayTimeBytes[0];
506
+
507
+ block[5] = delayTimeBytes[1];
508
+
509
+
510
+
511
+ //透過色指標 (Transparency Index, Transparent Color Index)
512
+
513
+ block[6] = 0xFF;
514
+
515
+
516
+
517
+ //ブロック終了符 (Block Terminator)
518
+
519
+ block[7] = 0x00;
520
+
521
+
522
+
523
+ return block;
524
+
525
+ }
526
+
341
527
  ```