C# JpgからPDFへ変換（１Jpgファイルを１ページとしたPDFファイルの作成）

###C# JpgからPDFへ変換
（１Jpgファイルを１ページとしたPDFファイルの作成）

## 〓出来ること
・1jpgあたり１ページとなる、PDFを作成(出来上がり複数ページ可)

## 〓準備
・file_list.txt　に　1行1jpgファイル名を記載
　　※このファイル名は固定。ソースコード中に記載。
・PDF化する画像を用意

## 〓ポイント
・ウィンドウズ dotNetフレームのみ
・コンパイルはWindowsのコマンドラインから
・PDFはスクラッチ（ゼロ）から内容記述

※PDFファイルを、何もないところから書き出しているので、本ソースのみで、（
（ライブラリ等一切必要なく）書き出している点が、メリット


## 〓実行準備
file_list.txt　
 - a.jpg
 - b.jpg
 - c.jpg
（単にjpg名を、テキストファイル内に１行ごと列挙）

## 〓実行
Jpg2Pdf_v03.exe xxx

※xxxは出来上がりのPDFファイル名を指定する

## 〓出来上がり
xxx.pdf


## 〓ソース

```csharp:Jpg2Pdf.cs

//c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:winexe Jpg2Pdf_v03.cs
using System.IO;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Drawing.Imaging;

public class Jpg2Pdf_v03
{

 public static void Main(string[] args)
 {

    string path1;//file name
    path1 = @".\temp.jpg";
    if(args.Length>0){
        path1 = @".\" + args[0];
    }else{
        System.Environment.Exit(0);
    }

    //■
    List<string> file_list = new List<string>();
    using (System.IO.StreamReader file = new System.IO.StreamReader(@".\file_list.txt", System.Text.Encoding.UTF8))
        {
            string line = "";
            while ((line = file.ReadLine()) != null)
            {
                file_list.Add(line);
            }

    //■

    string path2 = path1 + @".pdf";

    /// ★★
    using (FileStream fs2 = File.OpenWrite(path2))
    {


    Bitmap image1;
    FileInfo fi1;

    List<long> list = new List<long>();

    adTx(fs2, "%PDF-1.3");
    byte[] vals = { 0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0d, 0x0a };
    fs2.Write(vals, 0, vals.Length);


    int pg = 0;
    int objnm =0;
    int obj_rt =0;

    ////〓Pg
    pg = 0;
    foreach (var item in file_list){

        path1= item;

    image1 = new Bitmap(path1, true);
    fi1 = new FileInfo(path1);

    /// ★
    using (FileStream fs1 = File.OpenRead(path1))
    {

    objnm = (pg * 6) + 2;
    obj_rt = objnm;

    // index 2
    list.Add(fs2.Position);

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "<</Type /XObject");
    adTx(fs2, "/Subtype /Image");
    adTx(fs2, "/Filter /DCTDecode");
    adTx(fs2, "/ColorTransform 0");
    adTx(fs2, "/BitsPerComponent 8");

    // Format24bppRgb : Format8bppIndexed
    if (image1.PixelFormat == PixelFormat.Format24bppRgb){
        adTx(fs2, "/ColorSpace /DeviceRGB");
    }else{
        adTx(fs2, "/ColorSpace /DeviceGray");
    }

    adTx(fs2, "/Width " + image1.Width.ToString());
    adTx(fs2, "/Height " + image1.Height.ToString());
    adTx(fs2, "/Length " + fi1.Length.ToString() + ">>");



    adTx(fs2, "stream");
        byte[] b = new byte[1];
        while (fs1.Read(b,0,b.Length) > 0)
        {

            fs2.Write(b, 0, b.Length);
        }
    adTx(fs2, "");
    adTx(fs2, "endstream");
    adTx(fs2, "endobj");

    // index 3
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "<</Type /Page");
    adTx(fs2, "/Parent 1 0 R");
    adTx(fs2, "/MediaBox [0.0 0.0 595.2 841.68]");
    adTx(fs2, "/Contents " + (obj_rt+2) + " 0 R");
    adTx(fs2, "/Resources " + (obj_rt+4) + " 0 R");
    adTx(fs2, "/Annots " + (obj_rt+5) + " 0 R");
    adTx(fs2, ">>");
    adTx(fs2, "endobj");

    // index 4
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "<</Length " + (obj_rt+3) + " 0 R>>");
    adTx(fs2, "stream");
    adTx(fs2, "q");
    adTx(fs2, "1 0 0 1 0 0 cm");
    adTx(fs2, "1 0 0 1 0 0 cm");
    adTx(fs2, "595.2 0 0 841.68 0 0 cm");
    adTx(fs2, "/I0_0 Do");
    adTx(fs2, "Q");
    adTx(fs2, "endstream");
    adTx(fs2, "endobj");

    // index 5
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "67");
    adTx(fs2, "endobj");

    // index 6
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");
    adTx(fs2, "/XObject <<");
    adTx(fs2, "/I0_0 " + (obj_rt) + " 0 R");
    adTx(fs2, ">>");
    adTx(fs2, ">>");
    adTx(fs2, "endobj");

    // index 7
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "[]");
    adTx(fs2, "endobj");


    } /// ★

        pg ++;
    }
    ////〓Pg

    // index 8
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, objnm.ToString() + " 0 obj");
    adTx(fs2, "<</Type /Catalog");
    adTx(fs2, "/Pages 1 0 R");
    adTx(fs2, ">>");
    adTx(fs2, "endobj");

    // index 1
    list.Add(fs2.Position);

    adTx(fs2, "1 0 obj");
    adTx(fs2, "<</Type /Pages");
    //--------------
    string oj ="[";
    for(int lp = 0;lp<=(file_list.Count-1);lp++){/// ▲Pg数
        oj = oj + ((lp * 6)+3).ToString() + @" 0 R ";
    }
    oj = oj + "]";
    adTx(fs2, "/Kids " + oj);

    adTx(fs2, "/Count " + file_list.Count.ToString());  /// ▲Pg数
    //--------------
    adTx(fs2, ">>");
    adTx(fs2, "endobj");

    // index xref
    list.Add(fs2.Position);
    objnm ++;

    adTx(fs2, "xref");
    adTx(fs2, "0 " + objnm.ToString()); //15
    adTx(fs2, "0000000000 00000 f");

    string s;
    s = "0000000000" + list[(objnm-1)];
    s = s.Substring(s.Length - 10, 10);
    adTx(fs2, s + " 00000 n");


    for (int i = 0; i < (objnm-1); i++)
    {
        s = "0000000000" + list[i];
        s = s.Substring(s.Length - 10, 10);
        adTx(fs2, s + " 00000 n");
    }

    adTx(fs2, "trailer <</Size " + objnm.ToString() + " /Root " + (objnm-1).ToString() + " 0 R>>");

    adTx(fs2, "startxref");
    adTx(fs2, list[(objnm-1)].ToString());

    adTx(fs2, "%%EOF");


    } /// ★★


}}

    private static void adTx(FileStream fs, string value)
    {
        byte[] info = new UTF8Encoding(true).GetBytes(value);
        fs.Write(info, 0, info.Length);

        byte[] vals = { 0x0d}; // , 0x0a
        fs.Write(vals, 0, vals.Length);
    }


}

```


##参考

(C#) PDFを読み込んで、Stream内をすべて別ファイルに書き出す、サンプルソース
https://qiita.com/santarou6/items/5272458b1e9ff2058327

(C#) PDFを読み込んで、埋め込まれた画像をJPGファイルとして書き出す（DCTDecodeのStream内をママ書き出しているだけなのでかなり雑）
https://qiita.com/santarou6/items/5f011e266929558ede34