This takes in a byte array and any sort of IEnumerable of type int (List/Array/etc) to represent which page numbers to delete. This list is a normal 1 based index, meaning page 1 of the document is a 1 in the list.

For example, to delete pages 2, 5 and 6 you could pass in:

new List<int> {2, 5, 6}

Then with iText7, call the following:

public byte[] DeletePages(byte[] pdf, IEnumerable<int> pageNumbers)
{
    using (var inputStream = new MemoryStream(pdf))
    {
        using (var reader = new PdfReader(inputStream))
        {
            using (var outputStream = new MemoryStream())
            {
                using (var writer = new PdfWriter(outputStream))
                {
                    using (var document = new PdfDocument(reader, writer))
                    {
                        foreach (var pageNumber in pageNumbers)
                        {
                            document.RemovePage(pageNumber);
                        }
                    }
                }

                return outputStream.ToArray();
            }
        }
    }
}

As many iText7 Pdf objects implement IDisposable we have to manually release the unmanaged resources. In the order of above, the resources being managed are:

  1. MemoryStream for reading in the byte array.
  2. PdfReader to read the MemoryStream.
  3. Another MemoryStream to serve as the PDF stream after the pages have been deleted.
  4. PdfWriter to write to the output stream.
  5. PdfDocument to take in the reader and produce results in the writer.

Feel free to swap out the using blocks for .close() if that fits your style. We can also pass a stream instead - removing the need for the first MemoryStream using block.