2017-05-29 7 views
2

pngファイルを参照してください。イメージデータを参照して、ファイルサイズを変更せずに再度書き込みます。 libpng文書に基づいて、pngは可逆であり、圧縮の場合はのデフレートlz77を使用します。 libpngには、損失なしでイメージを読み書きすることを主張しているプロジェクトの例がありますが、ピクセル値は正しいですが、ファイル構造(IDAT、オプションのチャンクなど)を変更することができます。C(libpng)のファイルサイズを変更せずにpngファイルを読み書きする

私の明示的な質問 圧縮ストリーム(libpngのZstream)からエンコードパラメータ(deflate paramsやlz77 paramsなど)を抽出し、このパラメータを使用してrawファイルをエンコードして、入力ファイルと同じイメージファイルを変更せずに作成する方法?

これは私のコードです。私はinfo_ptrにparamsを保持しようとしましたが、イメージは書き込めませんが、動作しません。どうやってするの?

int main(int argc, char *argv[]) 
{ 
inname = argv[1]; 
outname = argv[2]; 

png_structrp read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
png_infop info_ptr = png_create_info_struct(read_ptr); 



if (!info_ptr) 
{ 
    png_destroy_read_struct(&read_ptr, (png_infopp)NULL, (png_infopp)NULL); 
} 

png_FILE_p imageFile, imageFile2, imageFileW; 
    imageFile=fopen(inname, "rb"); imageFileW = fopen(outname, "wb"); imageFile2 = fopen(inname, "rb"); 

int fileSize=fsize(imageFile2); 
unsigned char* bufImWrite = malloc(sizeof(char)*fileSize); 
fread(bufImWrite, 1, fileSize, imageFile2); 

png_init_io(read_ptr, imageFile); 

png_read_info(read_ptr, info_ptr); 


png_uint_32 height; 
height = info_ptr->height; 


png_bytep * row_pointers; 

row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); 
for (int y = 0; y < height; y++) 
    row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(read_ptr, info_ptr)); 


png_read_image(read_ptr, row_pointers); 


png_read_end(read_ptr, info_ptr); 


png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);; 
png_init_io(png_ptr, imageFileW); 
png_write_info(png_ptr, info_ptr); 
//png_set_compression_level(png_ptr, 9); 
//png_set_compression_window_bits(png_ptr, 15); 
//png_set_compression_strategy(png_ptr, 3); 
//png_set_compression_mem_level(png_ptr, 8); 

png_write_image(png_ptr, row_pointers); 
png_write_end(png_ptr, info_ptr); 


} 
+0

これは奇妙な要求です。ファイルを変更したくない場合は、コピーしてください。画像の内容を変更したい場合、まったく同じ圧縮率を達成することは不可能である可能性があります。一部のタグを変更する場合は、その場で変更してください。 –

+0

この質問は正しい@YvesDaoust(票を落とす?)。彼は生の画像データを取得し、このデータを再度圧縮して同じファイルを生成する必要があります。コピーとは異なります(圧縮科学)。この問題の解決策は何ですか? –

答えて

3

PNGファイルには、あなたが欲しいものを本当にできません、圧縮のために使用される正確なデフレート/ zlibのパラメータの記録が含まれていません。元のエンコーディングを保持する必要がある場合は、オリジナルのPNGファイルを破壊的に読み取るのではなく、そのままにしておく必要があります。

イメージデータを変更せずに補助PNGチャンクを変更する場合は、tweakpngなどのアプリケーションを使用して、元のPNGファイルのIHDR、PLTE、IDAT、およびIENDチャンクを新しいファイルにコピーします。

コメントが示唆しているように、圧縮データストリームを変更せずにウォーターマークを追加したい場合は、画像データが異なるため不可能です。リムーバブルウォーターマークが本当に必要な場合は、SVGなどの編集可能な形式を使用してウォーターマークを分離しておくか、別の部分にウォーターマークを保存できるAPNGなどの形式を使用します。その欠点は誰でも自分のコピーから透かしを取り除くことができることです。

+0

ありがとう@Glenn Randers-Pehrson、あなたのノートに基づいて、私はデコードしてpngファイルをエンコードできず、同じファイルを生成します。私は画像の透かし作成に取り組んでおり、私の方法はファイルサイズに制限されています。換言すれば、pngの圧縮データストリームに透かしビットを埋め込み、データの操作後に** adler **と** crc **の変更を考慮したいと思います。 **データ構造と画質を保存する**圧縮zlibストリームの最適な位置はどこですか? –

+0

ウォーターマークを追加する場合は、イメージデータを変更することになります。異なる圧縮イメージであるため、同じ圧縮データストリームを保持することは絶対に不可能です。 –

+0

私は、最初にオーバーレイされる第2のフレームとしてウォーターマークを追加するためにAPNGフォーマットを使用することは可能であろうが、それはおそらくこの質問の範囲外であると思われる。私はアイデアをあきらめて、再圧縮された画像データで生きていくことをお勧めします。 –

2

Glennの正しい応答に加えて、何らかの理由で圧縮に使用されたパラメータがあったとしても、圧縮は使用できなくなったコード、または専有で利用できないコードによって行われている可能性があります。いずれの場合も、正確な圧縮データを複製する方法はありません。 イメージを混乱させたくない場合は、元の圧縮データをそのまま使用してください。

関連する問題