GPT4o に画像を送信する JSON フォーマットで、赤線の部分が画像ファイルを Base64 でエンコードした文字列でした。この文字列を作成する部分を解説します。
画像データの取得方針
リッチテキストライトフィールドに Nomad から写真を添付する方法は、写真と添付ファイルの 2 種類の方法があります。写真を選択すると添付ファイルになります。カメラから撮影すると貼り付ける際にイメージの縮小が可能です。画像サイズを小さくしたいとき有効なのですが、この方法だとリッチテキストにインラインイメージ(リッチテキストに見える状態で貼り付けた画像)となります。
そこで今回は、添付ファイルとインラインイメージの双方に対応したいと思います。
ただ、インラインイメージは LotusScript の通常の NotesRichText*** クラスではアクセスできません。そこで、今回は DXL を使用して、リッチテキスト内のデータを取得します。
このシリーズにおいて、この記事だけは JSON ではなく DXL について記載しています。ご注意ください。なお、DXL を使用して、画像や添付ファイルを取得する方法については以下のリンクを参照ください。
画像取得関数
画像データを取得する関数は、大きく 2 つの処理に分かれています。まず、添付ファイルを探し、見つからない場合は、インラインイメージを取得しています。
戻り値は、取得した画像の Base64 文字列となります。
Private Function xGetImage_Base64(vnd As NotesDocument, ByVal vsFldName As String) As String '最初の添付ファイルを Base64 文字列で取得 xGetImage_Base64 = xGetDXL_FirstAttachment64(vnd, "Body") If xGetImage_Base64 = "" Then '添付はない(= 最初のインラインイメージを取得) xGetImage_Base64 = xGetDXL_FirstInlineImage64(vnd, "Body") End If End Function |
なお、添付ファイルを先にチェックしているには理由があります。
添付ファイルを DXL に変換するとそこにアイコンの画像が含まれます。この画像がインラインイメージと同じ構造となっています。先にインラインイメージを検索すると添付ファイルのアイコン画像を取得してしまう可能性があるからです。
最初の添付ファイルの取得
DXL Step-by-Step:#46)添付ファイルの取得 ① で紹介した関数とほぼ同じです。
ただ、API に送信するのも Base64 エンコード、DXL から取得するのも同じです。リンクの記事の関数はデコードしてバイナリデータで返す仕様だったのですが、そこを省き、取得した Base64 文字列をそのまま戻り値として返すようにしています。
Private Function xGetDXL_FirstAttachment64(vnd As NotesDocument, ByVal vsFld As String) As String 'DXL の準備 Dim dprs As NotesDOMParser Set dprs = xGetDOMParser(vnd) 'DOM ツリーのルートを取得 Dim ddn As NotesDOMDocumentNode Set ddn = dprs.Document 'リッチテキストの取得 Dim denRT As NotesDOMElementNode Set denRT = xGetDXL_item(ddn, vsFld) '添付情報の取得 Dim denRef As NotesDOMElementNode Set denRef = xGetDXL_FirstNodeByName(denRT, "attachmentref") If Not (denRef Is Nothing) Then 'ファイル名取得 Dim sName As String Dim sDisp As String sName = denRef.GetAttribute("name") sDisp = denRef.GetAttribute("displayname") '$FILE フィールド取得 Dim denFile As NotesDOMElementNode Set denFile = xGetDXL_FileItem(ddn, sName) 'Notes 内部の名称で検索 If Not (denFile Is Nothing) Then 'ファイルの中身を取得 Dim denData As NotesDOMElementNode Set denData = xGetDXL_FirstNodeByName(denFile, "filedata") If Not (denData Is Nothing) Then Dim dtn As NotesDOMTextNode Dim sB64 As String 'エンコードされたファイルを取得 Set dtn = denData.FirstChild sB64 = dtn.NodeValue '戻り値セット xGetDXL_FirstAttachment64 = sB64 End If End If End If End Function |
最初のインラインイメージの取得
こちらも #42)インラインイメージの取得 で紹介した関数とほぼ同じなのですが、上記度同様に、取得した Base64 文字列をそのまま戻り値として返すようにしています。
Private Function xGetDXL_FirstInlineImage64(vnd As NotesDocument, ByVal vsFld As String) As String 'DXL の準備 Dim dprs As NotesDOMParser Set dprs = xGetDOMParser(vnd) 'DOM ツリーのルートを取得 Dim ddn As NotesDOMDocumentNode Set ddn = dprs.Document 'リッチテキストの取得 Dim denRT As NotesDOMElementNode Set denRT = xGetDXL_item(ddn, vsFld) '画像の取得 Dim denPct As NotesDOMElementNode Set denPct = xGetDXL_FirstNodeByName(denRT, "picture") '画像ファイル取得 Dim denImg As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim dtn As NotesDOMTextNode Dim sB64 As String Dim asTag(2) As String asTag(0) = "png" asTag(1) = "gif" asTag(2) = "jpeg" '画像データの捜索 If Not(denPct Is Nothing) Then ForAll sTag In asTag Set denImg = xGetDXL_FirstNodeByName(denPct, sTag) If Not(denImg Is Nothing) Then 'エンコードされた画像データ取得 Set dtn = denImg.FirstChild sB64 = dtn.NodeValue '戻り値セット xGetDXL_FirstInlineImage64 = sB64 Exit ForAll End If End ForAll End If End Function |
その他サブ関数
上記 2 関数からコールされている関数群を列挙します。こちらにまとめた関数は過去の記事の関数をそのまま再掲しています。
◇ 文書を DXL に変換
Private Function xGetDOMParser(vnd As NotesDocument) As NotesDOMParser 'Dominoデータ を DXL に変換する準備 Dim dexp As NotesDXLExporter Set dexp = xns.CreateDXLExporter() Call dexp.SetInput(vnd) 'パーサーに変換する DXL をセット Dim dprs As NotesDOMParser Set dprs = xns.CreateDOMParser() Call dprs.SetInput(dexp) 'DXL 変換を実行 Call dexp.Process() Set xGetDOMParser = dprs End Function |
◇ 検索して最初のノードを取得
Private Function xGetDXL_FirstNodeByName(vdenParent As NotesDOMElementNode, ByVal vsName As String) As NotesDOMElementNode Dim dnl As NotesDOMNodeList On Error Resume Next '配下のノードを検索 Set dnl = vdenParent.GetElementsByTagName(vsName) If dnl.NumberOfEntries > 0 Then '最初のノードを戻り値にセット Set xGetDXL_FirstNodeByName = dnl.GetItem(1) End If End Function |
◇ フィールドを検索して取得
Private Function xGetDXL_item(vddn As NotesDOMDocumentNode, ByVal vsFld As String) As NotesDOMElementNode '文書のノードの取得 Dim denDoc As NotesDOMElementNode Set denDoc = vddn.DocumentElement 'itemノードをチェック Dim den As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim i As Integer Dim sFld As String Set dnl = denDoc.GetElementsByTagName("item") For i = 1 To dnl.NumberOfEntries Set den = dnl.GetItem(i) sFld = den.GetAttribute("name") If LCase(sFld) = LCase(vsFld) Then '戻り値セットしてループ脱出 Set xGetDXL_item = den Exit For End If Next End Function |
◇ 添付ファイルを検索して取得
Private Function xGetDXL_FileItem(vddn As NotesDOMDocumentNode, ByVal vsName As String) As NotesDOMElementNode '文書のノードの取得 Dim denDoc As NotesDOMElementNode Set denDoc = vddn.DocumentElement 'itemノードをチェック Dim denItem As NotesDOMElementNode Dim dnl As NotesDOMNodeList Dim i As Integer Dim sFld As String Dim sName As String Dim den As NotesDOMElementNode Set dnl = denDoc.GetElementsByTagName("item") For i = 1 To dnl.NumberOfEntries Set denItem = dnl.GetItem(i) sFld = denItem.GetAttribute("name") If LCase(sFld) = LCase("$FILE") Then '添付ファイルなのでチェックを継続 'object ノード取得 Set den = xGetDXL_FirstNodeByName(denItem, "object") If Not (den Is Nothing) Then 'file ノード取得 Set den = xGetDXL_FirstNodeByName(den, "file") If Not (den Is Nothing) Then '添付ファイルなので Notes 内部のファイル名取得 sName = den.GetAttribute("name") If LCase(sName) = LCase(vsName) Then 'ファイル名一致 '戻り値セットしてループ脱出 Set xGetDXL_FileItem = den 'file ノード Exit For End If End If End If End If Next End Function |
前回 | 作ってみよう | 次回 |
0 件のコメント:
コメントを投稿