質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

0回答

2620閲覧

UWP InkCanvas アニメーションGIFのバイナリ書き込みをすると背景が黒くなることについて

dylan

総合スコア26

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2017/04/06 09:49

編集2022/01/12 10:55

UWPでアプリ開発をしているものです。
InkCanvasで描いた絵をGIFとして書き出したいと思いGIFのファイルの構造を調べ、実装してみました。しかし、できたファイルをWindowsのフォトで開いてみると背景が黒になってしまいます。ファイルの書き込みが間違っているのでしょうか。ほかに原因があるとすれば何が考えられるでしょうか。
どなたかご教授ください。お願いします。
以下ファイル書き込みコードの一部です。

C#

1//アニメーションGif(isfメタデータの)を書き出す 2public async void Write(StorageFile file, UInt16 delayTime) 3{ 4 IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite); 5 MemoryStream memoryStream = new MemoryStream(); 6 BinaryWriter binaryWriter = new BinaryWriter(fileStream.AsStream()); 7 bool hasGlobalColorTable = false; //グローバルカラーテーブルがあるか 8 int colorTableSize = 0; //カラーテーブルのサイズ 9 10 //アプリケーションで指定したファイルのリアルタイム更新を遅延 11 //Prevent updates to the file until updates are 12 //finalized with call to CompleteUpdatesAsync. 13 CachedFileManager.DeferUpdates(file); 14 15 for (int i = 0; i < sketchBook.Count; i++) 16 { 17 //InkCanvasからすべてのstrokeを取得 18 IReadOnlyList<InkStroke> strokes = sketchBook[i].InkPresenter.StrokeContainer.GetStrokes(); 19 20 if (strokes.Count >= 0) 21 { 22 //メモリに保存 23 await sketchBook[i].InkPresenter.StrokeContainer.SaveAsync(memoryStream.AsOutputStream()); 24 25 //メモリの位置を0にする 26 memoryStream.Position = 0; 27 28 if (i == 0) 29 { 30 //Header読み込み、書き込み 31 //GIF89a 32 byte[] header = ReadBytes(memoryStream, 6); 33 binaryWriter.Write(header); 34 35 //Logical Screen Descriptor読み込み 36 byte[] screenDescriptor = ReadBytes(memoryStream, 7); 37 38 //Gif画像全体のサイズを設定 39 UInt16 width, height; 40 width = (UInt16)sketchBook[i].ActualWidth; 41 height = (UInt16)sketchBook[i].ActualHeight; 42 byte[] widthBytes = BitConverter.GetBytes(width); 43 byte[] heightBytes = BitConverter.GetBytes(height); 44 screenDescriptor[0] = widthBytes[0]; 45 screenDescriptor[1] = widthBytes[1]; 46 screenDescriptor[2] = heightBytes[0]; 47 screenDescriptor[3] = heightBytes[1]; 48 49 //背景色 50 screenDescriptor[5] = 0xFF; 51 52 //Global Color Tableがあるか 53 if ((screenDescriptor[4] & 0x80) != 0) 54 { 55 //Color Tableのサイズを取得 56 colorTableSize = screenDescriptor[4] & 0x07; 57 hasGlobalColorTable = true; 58 } 59 else 60 { 61 hasGlobalColorTable = false; 62 } 63 64 //Global Color Tableを使わない 65 //広域配色表フラグと広域配色表の寸法を消す 66 screenDescriptor[4] = (byte)(screenDescriptor[4] & 0x78); 67 68 //Logical Screen Descriptor書き込み 69 binaryWriter.Write(screenDescriptor); 70 71 //Application Extensionを追加 72 binaryWriter.Write(GetApplicationExtension(0)); 73 } 74 else 75 { 76 //HeaderとLogical Screen Descriptorをスキップ 77 memoryStream.Position = 6 + 7; 78 } 79 80 //Graphics Control Extension読み込み、書き込み 81 byte[] graphicsControlExtension = ReadBytes(memoryStream, 8); 82 binaryWriter.Write(GetGraphicControlExtension(delayTime)); 83 84 byte[] colorTable = null; 85 if (hasGlobalColorTable) 86 { 87 //Color Tableを取得、3はRGB 88 colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3); 89 } 90 91 //Image Descriptor読み込み 92 byte[] imageDescriptor = ReadBytes(memoryStream, 10); 93 94 //位置の設定 95 byte[] xBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.X); 96 byte[] yBytes = BitConverter.GetBytes((UInt16)sketchBook[i].InkPresenter.StrokeContainer.BoundingRect.Y); 97 imageDescriptor[1] = xBytes[0]; 98 imageDescriptor[2] = xBytes[1]; 99 imageDescriptor[3] = yBytes[0]; 100 imageDescriptor[4] = yBytes[1]; 101 102 if (!hasGlobalColorTable) 103 { 104 //Local Color Tableを持っているか 105 if ((imageDescriptor[9] & 0x80) == 0) 106 throw new Exception("Not found local color table."); 107 108 //Color Tableのサイズを取得 109 colorTableSize = imageDescriptor[9] & 7; 110 111 //Color Tableを取得 112 colorTable = ReadBytes(memoryStream, (int)Math.Pow(2, colorTableSize + 1) * 3); 113 } 114 115 //狭域配色表フラグ (Local Color Table Flag)と狭域配色表の寸法を追加 116 imageDescriptor[9] = (byte)(imageDescriptor[9] | 0x80 | colorTableSize); 117 118 //Image Descriptor書き込み 119 binaryWriter.Write(imageDescriptor); 120 121 //Local Color Table書き込み 122 binaryWriter.Write(colorTable); 123 124 //Image Data読み込み、書き込み(終了部0x3Bは書き込まない) 125 byte[] imageDataBytes = ReadBytes(memoryStream, (int)(memoryStream.Length - memoryStream.Position - 1)); 126 binaryWriter.Write(imageDataBytes); 127 128 //0x3Bを読み飛ばし 129 byte[] end = ReadBytes(memoryStream, 1); 130 131 if (i == sketchBook.Count - 1) 132 { 133 //終了部(Trailer)書き込み 134 binaryWriter.Write((byte)0x3B); 135 } 136 137 //MemoryStreamをリセット 138 memoryStream.SetLength(0); 139 } 140 } 141 142 //指定したファイルの更新を開始 143 //Finalize write so other apps can update file. 144 Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file); 145 146 //ファイルが保存されたとき 147 if (status == Windows.Storage.Provider.FileUpdateStatus.Complete) 148 { 149 } 150 //ファイルが正常に保存されなかったとき 151 else 152 { 153 } 154 155 await memoryStream.FlushAsync(); 156 157 await fileStream.FlushAsync(); 158 159 memoryStream.Dispose(); 160 161 binaryWriter.Dispose(); 162 163 fileStream.Dispose(); 164} 165 166//MemoryStreamの現在の位置から指定されたサイズのバイト配列を読み込む 167//memoryStream : 読み取るMemoryStream 168//count : 読み取るバイトのサイズ 169//戻り値 : 読み取れたバイト配列 170static byte[] ReadBytes(MemoryStream memoryStream, int count) 171{ 172 byte[] bytes = new byte[count]; 173 memoryStream.Read(bytes, 0, count); 174 return bytes; 175} 176 177//Netscape Application Extensionブロックを返す 178//loopCount : 繰り返す回数、0で無限 179//戻り値 : Netscape Application Extensionブロックのbyte配列 180static byte[] GetApplicationExtension(UInt16 loopCount) 181{ 182 byte[] block = new byte[19]; 183 184 //拡張導入符(Extension Introducer) 185 block[0] = 0x21; 186 187 //アプリケーション拡張ラベル(Application Extension Label) 188 block[1] = 0xFF; 189 190 //ブロック寸法(Block Size) 191 block[2] = 0x0B; 192 193 //アプリケーション識別名(Application Identifier) 194 block[3] = (byte)'N'; 195 block[4] = (byte)'E'; 196 block[5] = (byte)'T'; 197 block[6] = (byte)'S'; 198 block[7] = (byte)'C'; 199 block[8] = (byte)'A'; 200 block[9] = (byte)'P'; 201 block[10] = (byte)'E'; 202 203 //アプリケーション確証符号(Application Authentication Code) 204 block[11] = (byte)'2'; 205 block[12] = (byte)'.'; 206 block[13] = (byte)'0'; 207 208 //データ副ブロック寸法(Data Sub-block Size) 209 block[14] = 0x03; 210 211 //詰め込み欄[ネットスケープ拡張コード(Netscape Extension Code)] 212 block[15] = 0x01; 213 214 //繰り返し回数(Loop Count) 215 byte[] loopCountBytes = BitConverter.GetBytes(loopCount); 216 block[16] = loopCountBytes[0]; 217 block[17] = loopCountBytes[1]; 218 219 //ブロック終了符(Block Terminator) 220 block[18] = (byte)0x00; 221 222 return block; 223} 224 225//Graphic Control Extensionブロックを返す 226//delayTime : 遅延時間(100分の1秒単位) 227//戻り値 : Graphic Control Extensionブロックのbyte配列 228static byte[] GetGraphicControlExtension(UInt16 delayTime) 229{ 230 byte[] block = new byte[8]; 231 232 //拡張導入符(Extension Introducer) 233 block[0] = 0x21; 234 235 //グラフィック制御ラベル(Graphic Control Label) 236 block[1] = 0xF9; 237 238 //ブロック寸法(Block Size, Byte Size) 239 block[2] = 0x04; 240 241 //詰め込み欄(Packed Field) 242 //透過色指標を使う時は+1 243 //消去方法 : そのまま残す+4、背景色でつぶす+8、直前の画像に戻す+12 244 block[3] = 0x00 + 8; 245 246 //遅延時間(Delay Time) 247 byte[] delayTimeBytes = BitConverter.GetBytes(delayTime); 248 block[4] = delayTimeBytes[0]; 249 block[5] = delayTimeBytes[1]; 250 251 //透過色指標 (Transparency Index, Transparent Color Index) 252 block[6] = 0xFF; 253 254 //ブロック終了符 (Block Terminator) 255 block[7] = 0x00; 256 257 return block; 258}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tak1wa

2017/04/10 13:18

「InkCanvasで描いた絵をGIFとして書き出したいと思い」とのことですが、gifバイナリは自前で作成する前提でしたか。
dylan

2017/04/11 00:32

回答ありがとうございます。アニメーションGIFとしして複数のInkCanvas(複数コマ)を1つのファイルに書き出すつもりです。なので調べた限りではバイナリを自前で作成する方法しかわからなかったので
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問