@@ -36,6 +36,9 @@ export function getPngMetadata(buffer: ArrayBuffer): Record<string, string> {
3636 offset + 8 + length
3737 ) ;
3838 const contentJson = new TextDecoder ( "utf-8" ) . decode ( contentArraySegment ) ;
39+
40+ if ( txt_chunks [ keyword ] )
41+ console . warn ( `Duplicated keyword ${ keyword } has been overwritten` ) ;
3942 txt_chunks [ keyword ] = contentJson ;
4043 }
4144
@@ -71,7 +74,7 @@ ref: png chunk struct:
7174export function setPngMetadata (
7275 buffer : ArrayBuffer ,
7376 new_txt_chunks : Record < string , string >
74- ) : Uint8Array < ArrayBufferLike > {
77+ ) : Uint8Array {
7578 // Get the PNG data as a Uint8Array
7679 const pngData = new Uint8Array ( buffer ) ;
7780 const newPngChunks : Uint8Array [ ] = [ ] ;
@@ -96,9 +99,7 @@ export function setPngMetadata(
9699 if ( type === "tEXt" || type == "comf" || type === "iTXt" ) {
97100 // Get the keyword
98101 let keyword_end = offset + 8 ;
99- while ( pngData [ keyword_end ] !== 0 ) {
100- keyword_end ++ ;
101- }
102+ while ( pngData [ keyword_end ] !== 0 ) keyword_end ++ ;
102103 const keyword = String . fromCharCode (
103104 ...pngData . slice ( offset + 8 , keyword_end )
104105 ) ;
@@ -163,6 +164,7 @@ export function setPngMetadata(
163164 newPngChunk . set ( encoded , 8 ) ;
164165 dataView . setUint32 ( 8 + chunkLength , chunkCRC32 ) ;
165166 newPngChunks . push ( newPngChunk ) ;
167+ delete new_txt_chunks [ keyword ] ; //mark used
166168 }
167169 } else {
168170 // if this keyword is not in new_txt_chunks,
@@ -177,7 +179,28 @@ export function setPngMetadata(
177179 offset += 12 + length ;
178180 }
179181
180- // Concatenate the new PNG chunks
182+ // If no EXIF section was found, add new metadata chunks
183+ Object . entries ( new_txt_chunks ) . map ( ( [ keyword , content ] ) => {
184+ // console.log(`Adding exif section for ${keyword}`);
185+ const encoded = new TextEncoder ( ) . encode ( keyword + "\x00" + content ) ;
186+ const chunkLength = encoded . length ;
187+ const chunkType = new TextEncoder ( ) . encode ( "tEXt" ) ;
188+
189+ // Calculate crc32
190+ const crcTarget = new Uint8Array ( chunkType . length + encoded . length ) ;
191+ crcTarget . set ( chunkType , 0 ) ;
192+ crcTarget . set ( encoded , chunkType . length ) ;
193+ const chunkCRC32 = crc32FromArrayBuffer ( crcTarget ) ;
194+
195+ const newPngChunk = new Uint8Array ( 8 + chunkLength + 4 ) ;
196+ const dataView = new DataView ( newPngChunk . buffer ) ;
197+ dataView . setUint32 ( 0 , chunkLength ) ;
198+ newPngChunk . set ( chunkType , 4 ) ;
199+ newPngChunk . set ( encoded , 8 ) ;
200+ dataView . setUint32 ( 8 + chunkLength , chunkCRC32 ) ;
201+ newPngChunks . push ( newPngChunk ) ;
202+ } ) ;
203+
181204 const newPngData = concatUint8Arrays ( newPngChunks ) ;
182205 return newPngData ;
183206}
0 commit comments