]> git.ipfire.org Git - thirdparty/cups-filters.git/commitdiff
Add crop-to-fit scaling feature. 92/head
authordh <dhirajyadav135@gmail.com>
Fri, 22 Feb 2019 15:55:33 +0000 (21:25 +0530)
committerdh <dhirajyadav135@gmail.com>
Mon, 4 Mar 2019 21:49:20 +0000 (03:19 +0530)
Input file is cropped and printed. We don't do scaling in crop-to-fit.
Fixes #65. imagetoraster, imagetopdf and pdftopdf filters are mutually exclusive.

"-o fill" option is now equivalent to "print-scaling=fill".

filter/imagetopdf.c
filter/imagetoraster.c
filter/pdftopdf/pdftopdf.cc
filter/pdftopdf/pdftopdf_processor.cc
filter/pdftopdf/pdftopdf_processor.h
filter/pdftopdf/qpdf_pdftopdf_processor.cc
filter/pdftopdf/qpdf_pdftopdf_processor.h

index 311e372aab0d5d916e1bdc5801e28dfa1f65269a..0bf2618dddc700b275d830dd58fc2dde36603008 100644 (file)
@@ -694,6 +694,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   ppd_attr_t *attr;
   int pl,pr;
   int fillprint = 0;  /* print-scaling = fill */
+  int cropfit = 0;  /* -o crop-to-fit = true */
  /*
   * Make sure status messages are not buffered...
   */
@@ -818,6 +819,21 @@ main(int  argc,                            /* I - Number of command-line arguments */
         fillprint = 1;
     }
   }
+  else if((val = cupsGetOption("fill",num_options,options))!=0) {
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      fillprint = 1;
+    }
+  }
+  /*
+   * crop-to-fit
+   */
+  if((val = cupsGetOption("crop-to-fit",num_options,options))!= NULL){
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      cropfit=1;
+    }
+  }
 
   if ((val = cupsGetOption("OutputOrder",num_options,options)) != 0) {
     if (!strcasecmp(val, "Reverse")) {
@@ -981,26 +997,26 @@ main(int  argc,                           /* I - Number of command-line arguments */
   colorspace = ColorDevice ? CUPS_IMAGE_RGB_CMYK : CUPS_IMAGE_WHITE;
 
   img = cupsImageOpen(filename, colorspace, CUPS_IMAGE_WHITE, sat, hue, NULL);
-
-  if(fillprint)
+  if(fillprint||cropfit)
   {
     float w = (float)cupsImageGetWidth(img);
     float h = (float)cupsImageGetHeight(img);
     float pw = PageRight-PageLeft;
     float ph = PageTop-PageBottom;
-    char temp[3072];
-    char tempfilename[1024];
     int tempOrientation = Orientation;
-    if ((cupsTempFd(tempfilename, sizeof(tempfilename))) < 0)
-    {
-      perror("ERROR: Unable to copy image file");
-      return (1);
-    }
     char *val;
+    int flag = 3;
     if((val = cupsGetOption("orientation-requested",num_options,options))!=NULL)
     {
       tempOrientation = atoi(val);
     }
+    else if((val = cupsGetOption("landscape",num_options,options))!=NULL)
+    {
+      if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+      {
+        tempOrientation = 4;
+      }
+    }
     if(tempOrientation>0)
     {
       if(tempOrientation==4||tempOrientation==5)
@@ -1008,33 +1024,83 @@ main(int  argc,                         /* I - Number of command-line arguments */
         float temp = pw;
         pw = ph;
         ph = temp;
+        flag = 4;
       }
     }
     if(tempOrientation==0)
     {
-      float ratio = ph/pw;
-      if(h/w < ratio)
+      int temp1 = pw,
+          temp2 = ph,
+          temp3 = pw,
+          temp4 = ph;
+      if(temp1>w) temp1 = w;
+      if(temp2>h) temp2 = h;
+      if(temp3>h) temp3 = h;
+      if(temp4>w) temp4 = w; 
+      if(temp1*temp2<temp3*temp4)
       {
-        float temp = pw;
+        int temp = pw;
         pw = ph;
         ph = temp;
+        flag = 4;
       }
     }
-    float final_w,final_h;
-    if(w*ph/pw <=h){
-      final_w =w;
-      final_h =w*ph/pw; 
+    if(fillprint){
+      float final_w,final_h;
+      if(w*ph/pw <=h){
+        final_w =w;
+        final_h =w*ph/pw; 
+      }
+      else{
+        final_w = h*pw/ph;
+        final_h = h;
+      }
+      float posw=(w-final_w)/2,posh=(h-final_h)/2;
+      posw = (1+XPosition)*posw;
+      posh = (1-YPosition)*posh;
+      cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
+      cupsImageClose(img);
+      img = img2;
     }
-    else{
-      final_w = h*pw/ph;
-      final_h = h;
+    else {
+      float final_w=w,final_h=h;
+      if(final_w>pw)
+      {
+        final_w = pw;
+      }
+      if(final_h>ph)
+      {
+        final_h = ph;
+      }
+      if((fabs(final_w-w)>0.5*w)||(fabs(final_h-h)>0.5*h))
+      {
+        fprintf(stderr,"[DEBUG]: Ignoring crop-to-fit option!\n");
+        cropfit=0;
+      }
+      else{
+        float posw=(w-final_w)/2,posh=(h-final_h)/2;
+        posw = (1+XPosition)*posw;
+        posh = (1-YPosition)*posh;
+        cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
+        cupsImageClose(img);
+        img = img2;
+        if(flag==4)
+        {
+          PageBottom+=(PageTop-PageBottom-final_w)/2;
+          PageTop = PageBottom+final_w;
+          PageLeft +=(PageRight-PageLeft-final_h)/2;
+          PageRight = PageLeft+final_h;
+        }
+        else{
+          PageBottom+=(PageTop-PageBottom-final_h)/2;
+          PageTop = PageBottom+final_h;
+          PageLeft +=(PageRight-PageLeft-final_w)/2;
+          PageRight = PageLeft+final_w;
+        }
+        if(PageBottom<0) PageBottom = 0;
+        if(PageLeft<0) PageLeft = 0;
+     }
     }
-    float posw=(w-final_w)/2,posh=(h-final_h)/2;
-    posw = (1+XPosition)*posw;
-    posh = (1-YPosition)*posh;
-    cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
-    cupsImageClose(img);
-    img = img2;
   }
 
 #if defined(USE_CONVERT_CMD) && defined(CONVERT_CMD)
index 43faa015ab017834aabaa1759cce32ebf5132f0b..5b5674d8f295e1a8943b0f167e3c0255eba87ada 100644 (file)
@@ -191,6 +191,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   cm_calibration_t      cm_calibrate;   /* Are we color calibrating the device? */
   int                   cm_disabled;    /* Color management disabled? */
   int fillprint = 0;  /* print-scaling = fill */
+  int cropfit = 0;             /* -o crop-to-fit */
  /*
   * Make sure status messages are not buffered...
   */
@@ -394,6 +395,18 @@ main(int  argc,                            /* I - Number of command-line arguments */
         fillprint = 1;
     }
   }
+  else if((val = cupsGetOption("fill",num_options,options))!=0) {
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      fillprint = 1;
+    }
+  }
+  if((val = cupsGetOption("crop-to-fit",num_options,options))!= NULL){
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      cropfit=1;
+    }
+  }
 
   if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
   {
@@ -696,24 +709,26 @@ main(int  argc,                           /* I - Number of command-line arguments */
     img = cupsImageOpen(filename, primary, secondary, sat, hue, lut);
   if(img!=NULL)
   {
-    if(fillprint)
+    if(fillprint||cropfit)
     {
       float w = (float)cupsImageGetWidth(img);
       float h = (float)cupsImageGetHeight(img);
       float pw = PageRight-PageLeft;
       float ph = PageTop-PageBottom;
-      char temp[3072],*val;
-      char tempfilename[1024];
+      char *val;
       int tempOrientation = Orientation;
-      if ((cupsTempFd(tempfilename, sizeof(tempfilename))) < 0)
-      {
-        perror("ERROR: Unable to copy image file");
-        return (1);
-      }
+      int flag =3;
       if((val = cupsGetOption("orientation-requested",num_options,options))!=NULL)
       {
         tempOrientation = atoi(val);
       }
+      else if((val = cupsGetOption("landscape",num_options,options))!=NULL)
+      {
+        if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+        {
+          tempOrientation = 4;
+        }
+      }
       if(tempOrientation>0)
       {
         if(tempOrientation==4||tempOrientation==5)
@@ -721,35 +736,78 @@ main(int  argc,                           /* I - Number of command-line arguments */
           float temp = pw;
           pw = ph;
           ph = temp;
+          flag = 4;
         }
       }
       if(tempOrientation==0)
       {
-        float ratio = ph/pw;
-        if(h/w < ratio)
+        if(min(pw,w)*min(ph,h)<min(pw,h)*min(ph,w))
         {
-          float temp = pw;
+          int temp = pw;
           pw = ph;
           ph = temp;
+          flag = 4;
         }
       }
-      // Final width and height of cropped image.
-      float final_w,final_h;
-      if(w*ph/pw <=h){
-        final_w =w;
-        final_h =w*ph/pw; 
-      }
-      else{
-        final_w = h*pw/ph;
-        final_h = h;
+      if(fillprint)
+      {
+        // Final width and height of cropped image.
+        float final_w,final_h;
+        if(w*ph/pw <=h){
+          final_w =w;
+          final_h =w*ph/pw; 
+        }
+        else{
+          final_w = h*pw/ph;
+          final_h = h;
+        }
+        // posw and posh are position of the cropped image along width and height.
+        float posw=(w-final_w)/2,posh=(h-final_h)/2;
+        posw = (1+XPosition)*posw;
+        posh = (1-YPosition)*posh;
+        cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
+        cupsImageClose(img);
+        img = img2;
       }
-      // posw and posh are position of the cropped image along width and height.
-      float posw=(w-final_w)/2,posh=(h-final_h)/2;
-      posw = (1+XPosition)*posw;
-      posh = (1-YPosition)*posh;
-      cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
-      cupsImageClose(img);
-      img = img2;
+      else {
+        float final_w=w,final_h=h;
+        if(w>pw)
+        {
+          final_w = pw;
+        }
+        if(h>ph)
+        {
+          final_h = ph;
+        }
+        if((fabs(final_w-w)>0.5*w)||(fabs(final_h-h)>0.5*h))
+        {
+          fprintf(stderr,"[DEBUG]: Ignoring crop-to-fit option!\n");
+          cropfit=0;
+        }
+        else{
+          float posw=(w-final_w)/2,posh=(h-final_h)/2;
+          posw = (1+XPosition)*posw;
+          posh = (1-YPosition)*posh;
+          cups_image_t *img2 = cupsImageCrop(img,posw,posh,final_w,final_h);
+          cupsImageClose(img);
+          img = img2;
+          if(flag==4)
+          {
+            PageBottom+=(PageTop-PageBottom-final_w)/2;
+            PageTop = PageBottom+final_w;
+            PageLeft +=(PageRight-PageLeft-final_h)/2;
+            PageRight = PageLeft+final_h;
+          }
+          else{
+            PageBottom+=(PageTop-PageBottom-final_h)/2;
+            PageTop = PageBottom+final_h;
+            PageLeft +=(PageRight-PageLeft-final_w)/2;
+            PageRight = PageLeft+final_w;
+          }
+          if(PageBottom<0) PageBottom = 0;
+          if(PageLeft<0) PageLeft = 0;
+        }
+      }        
     }
   }
   if (argc == 6)
index f2d9b37c9ac8d3016d6e510f0886c97ded3bc6a2..bf29ec0f6fc8097993e996ffb2f1cd1714e01f7c 100644 (file)
@@ -331,6 +331,21 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces
       param.fillprint=true;
     }
   }
+  else if((val = cupsGetOption("fill",num_options,options))!=0) {
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      param.fillprint = true;
+    }
+  }
+  /*
+   * crop-to-fit
+   */
+  if((val = cupsGetOption("crop-to-fit",num_options,options))!= NULL){
+    if(!strcasecmp(val,"true")||!strcasecmp(val,"yes"))
+    {
+      param.cropfit=1;
+    }
+  }
 
   if (ppd && (ppd->landscape < 0)) { // direction the printer rotates landscape (90 or -90)
     param.normal_landscape=ROT_270;
index e6d4e142b82f8fe69ba81b48a51d20510c8cbb59..7f62b4f16d45b9aaa2ffd2b59a3a16eb6e43a862 100644 (file)
@@ -175,12 +175,12 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters &param) // {{
   }
   const int numPages=std::max(shuffle.size(),pages.size());
 
-  if(param.fillprint){
-    fprintf(stderr,"Cropping input pdf and Enabling fitplot.%d\n");
-    for(int i=0;i<pages.size();i++)
+  if(param.fillprint||param.cropfit){
+    fprintf(stderr,"[DEBUG]: Cropping input pdf and Enabling fitplot.\n");
+    for(int i=0;i<(int)pages.size();i++)
     {
       std::shared_ptr<PDFTOPDF_PageHandle> page = pages[i];
-      Rotation currRot = page->crop(param.page,param.orientation,param.xpos,param.ypos);
+      Rotation currRot = page->crop(param.page,param.orientation,param.xpos,param.ypos,!param.cropfit);
     }
     param.fitplot = 1;
   }
@@ -332,7 +332,20 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters &param) // {{
       if (!param.fitplot) {
         curpage->add_subpage(page,pgedit.xpos+xpos,pgedit.ypos+ypos,pgedit.scale,&rect);
       } else {
-        curpage->add_subpage(page,pgedit.xpos+xpos,pgedit.ypos+ypos,pgedit.scale);
+        if(param.cropfit){
+          double xpos2 = (param.page.right-param.page.left-(page->getRect().width))/2;
+          double ypos2 = (param.page.top-param.page.bottom-(page->getRect().height))/2;
+          if(param.orientation==ROT_270||param.orientation==ROT_90)
+          {
+            xpos2 = (param.page.right-param.page.left-(page->getRect().height))/2;
+            ypos2 = (param.page.top-param.page.bottom-(page->getRect().width))/2;
+            curpage->add_subpage(page,ypos2+param.page.bottom,xpos2+param.page.left,1);
+          }else{
+          curpage->add_subpage(page,xpos2+param.page.left,ypos2+param.page.bottom,1);
+          }
+        }
+        else
+          curpage->add_subpage(page,pgedit.xpos+xpos,pgedit.ypos+ypos,pgedit.scale);
       }
 
 #ifdef DEBUG
index a5128a69150df7fb635cbb9a4ae3dc3ef2134b74..d71fc16af18716848de7353ad854c767dec258af 100644 (file)
@@ -15,6 +15,7 @@ ProcessingParameters()
     user(0),title(0),
     fitplot(false),
     fillprint(false),  //print-scaling = fill
+    cropfit(false),
     orientation(ROT_0),normal_landscape(ROT_270),
     paper_is_landscape(false),
     duplex(false),
@@ -56,6 +57,7 @@ ProcessingParameters()
   const char *user, *title; // will stay around
   bool fitplot;
   bool fillprint;   //print-scaling = fill
+  bool cropfit;     // -o crop-to-fit
   PageRect page;
   Rotation orientation,normal_landscape;  // normal_landscape (i.e. default direction) is e.g. needed for number-up=2
   bool paper_is_landscape;
@@ -108,7 +110,7 @@ class PDFTOPDF_PageHandle {
   // fscale:  inverse_scale (from nup, fitplot)
   virtual void add_border_rect(const PageRect &rect,BorderType border,float fscale) =0;
   // TODO?! add standalone crop(...) method (not only for subpages)
-  virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos) =0;
+  virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale) =0;
   virtual void add_subpage(const std::shared_ptr<PDFTOPDF_PageHandle> &sub,float xpos,float ypos,float scale,const PageRect *crop=NULL) =0;
   virtual void mirror() =0;
   virtual void rotate(Rotation rot) =0;
index a136edf44f4957d4d517fcb237d85d62c0cc763b..0761a4240f71112f319e64409808e463ad84286d 100644 (file)
@@ -174,8 +174,9 @@ void QPDF_PDFTOPDF_PageHandle::add_border_rect(const PageRect &_rect,BorderType
 /*
  *  This crop function is written for print-scaling=fill option.
  *  Trim Box is used for trimming the page in required size.
+ *  scale tells if we need to scale input file.
  */
-Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos)
+Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale)
 {
   page.assertInitialized();
   if(orientation==ROT_0||orientation==ROT_180)
@@ -195,16 +196,23 @@ Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orient
   {
     std::swap(pageHeight,pageWidth);
   }
-  if(width*pageHeight/pageWidth<=height)
+  if(scale)
   {
-    final_w = width;
-    final_h = width*pageHeight/pageWidth;
+    if(width*pageHeight/pageWidth<=height)
+    {
+      final_w = width;
+      final_h = width*pageHeight/pageWidth;
+    }
+    else{
+      final_w = height*pageWidth/pageHeight;
+      final_h = height;
+    }
   }
   else{
-    final_w = height*pageWidth/pageHeight;
-    final_h = height;
+    final_w = std::min(width,pageWidth);
+    final_h = std::min(height,pageHeight);
   }
-
+  fprintf(stderr,"After Cropping: %lf %lf %lf %lf\n",width,height,final_w,final_h);
   double posw = (width-final_w)/2,
         posh = (height-final_h)/2;
   // posw, posh : Position along width and height respectively.
index a521c862436c484fb6c973c31d83f3c74709f90b..d1394a8afea78957dcf23c86114da5b0326288eb 100644 (file)
@@ -12,7 +12,7 @@ class QPDF_PDFTOPDF_PageHandle : public PDFTOPDF_PageHandle {
   virtual void mirror();
   virtual void rotate(Rotation rot);
   virtual void add_label(const PageRect &rect, const std::string label);
-  virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos);
+  virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale);
   void debug(const PageRect &rect,float xpos,float ypos);
  private:
   bool isExisting() const;