3 # pdfstrip.py - strip objects from PDF files by specifying objects IDs
 
   5 # Copyright (C) 2016  Antonio Ospite <ao2@ao2.it>
 
   7 # This program is free software: you can redistribute it and/or modify
 
   8 # it under the terms of the GNU General Public License as published by
 
   9 # the Free Software Foundation, either version 3 of the License, or
 
  10 # (at your option) any later version.
 
  12 # This program is distributed in the hope that it will be useful,
 
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15 # GNU General Public License for more details.
 
  17 # You should have received a copy of the GNU General Public License
 
  18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
  24 from pdfrw import PdfReader, PdfWriter
 
  25 from pdfrw.objects.pdfindirect import PdfIndirect
 
  28 # pylint: disable=invalid-name
 
  29 logger = logging.getLogger(__name__)
 
  30 console_handler = logging.StreamHandler()
 
  31 formatter = logging.Formatter('[%(levelname)s] %(funcName)s:%(lineno)d %(message)s')
 
  32 console_handler.setFormatter(formatter)
 
  33 logger.addHandler(console_handler)
 
  34 logger.propagate = False
 
  37 def strip_objects(pdf, objects_ids):
 
  38     for i, page in enumerate(pdf.pages):
 
  39         logger.debug("Page %d", i + 1)
 
  42         if not page.Resources.XObject:
 
  45         # Map all the objects in the page using the objects id as the key and
 
  46         # the resource name as the value.
 
  47         name_map = {indirect_obj.indirect[0]: name for name, indirect_obj in page.Resources.XObject.items()}
 
  48         logger.debug("name_map: %s", name_map)
 
  50         logger.debug("Before %s", page.Resources.XObject.keys())
 
  52         for obj in objects_ids:
 
  54                 del page.Resources.XObject[name_map[obj]]
 
  56         logger.debug("After  %s\n", page.Resources.XObject.keys())
 
  61 def validate_objects_ids(objects_ids_string):
 
  63         objects_ids = [int(obj) for obj in objects_ids_string.split(',')]
 
  64     except (IndexError, ValueError):
 
  65         raise argparse.ArgumentTypeError("%s contains an invalid value" % objects_ids_string)
 
  71     parser = argparse.ArgumentParser()
 
  73     parser.add_argument("input_filename",
 
  74                         help="the input PDF file (better if uncompressed)")
 
  75     parser.add_argument("output_filename",
 
  76                         help="the output PDF file")
 
  77     parser.add_argument("objects_ids",
 
  78                         type=validate_objects_ids,
 
  79                         help="a comma-separated list of objects IDs")
 
  80     parser.add_argument("-d", "--debug", action="store_true",
 
  81                         help="enable debug output")
 
  82     args = parser.parse_args()
 
  85         logger.setLevel(logging.DEBUG)
 
  87     pdf_data = PdfReader(args.input_filename)
 
  89     pdf_data = strip_objects(pdf_data, args.objects_ids)
 
  91     PdfWriter().write(args.output_filename, pdf_data)
 
  96 if __name__ == '__main__':