Overblog Suivre ce blog
Editer la page Administration Créer mon blog
/ / /

Ce script permet d'imprimer un document par morceaux à l'échelle 1, quand l'image est trop grande pour l'imprimante, tout en minimisant la surface de papier utilisé. Selon la forme de l'image et l'imprimante, les morceaux sont découpés dans le  mode optimal : portrait ou paysage.  

Les paramètres de l'imprimante doivent être définis dans la section PARAMETRES, surtout les marges non imprimées  aux bords du papier.

Dans cette version, l'imprimante doit être configurée en mode portrait (les morceaux en paysage sont tournés automatiquement).

 

Il est possible également de signaler des marges déjà existantes autour de l'image, ce qui permet de ne pas les imprimer et de gagner éventuellement beaucoup de papier. Par exemple une planche de BD en A3 peut ainsi être imprimée en deux feuilles A4, ce qui ne serait pas possible si la totalité du A3 devait être imprimé. En effet, à cause des marges de l'imprimante il faudrait 4 feuilles.

 

Enfin l'image peut être imprimée avec un cadre pour faciliter ensuite le découpage du papier si besoin.  

 

C'est évidemment un outil essentiel pour  imprimer une planche mise en place avec Photoshop afin de la décalquer  ensuite sur du bon papier à la table lumineuse, ou simplement pour imprimer un poster.

  

msnp005 72A3 

Voici par exemple une planche A3 dont les marges droite et gauche peuvent être ignorées sur 8mm  lors de l'impression. Ces marges peuvent être paramétrées dans le script.

 

 

 

 

 

 

 

 

 

 

 

L'image ci-dessous, obtenue automatiquement par le script, montre un découpage (par les lignes grises) en seulement  trois feuilles A4 portrait. Si les marges hautes et basses avaient pu être ignorées aussi (ce n'est pas le cas à cause du titre et de la signature) l'impression aurait utilisé deux feuilles seulement!

 

  Note: Les marges de l'imprimante sont en dehors du cadre gris.

 

 msnp005 print72b

Si ce script vous intéresse dans une version plus conviviale, c'est-à-dire avec une interface utilisateur qui permette de règler facilement les paramètres sans modifier le script, laisssez un message sur le blog.

 

 Copier le script qui suit jusqu'à la fin du texte dans un fichier .JSX. L'exécuter par le menu  Fichier:Scripts:Parcourir. 

/************************************************************************
                IMPRESSION D'UNE IMAGE PAR MORCEAUX
 ************************************************************************
 Le but est d'imprimer l'image a l'echelle 1 sur un minimum de papier.
 L'imprimante doit etre configuree selon la section "Parametres".
 Inscrire dans les variables PrintMargX les valeurs minimum des marges
 (ou plus) imposees par l'imprimante, sinon le document sera tronque.
 ************************************************************************
 19/06/2012 Habaki V1r01b: Marges d'image et impression d'un cadre
 14/06/2012 Habaki V1r01 : Creation
 ************************************************************************/
var ModName   = "Impression";
var jpegOptions  = new JPEGSaveOptions();
var RulerUnits  = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var BGColor  = backgroundColor.rgb.hexValue;
/*----------------------------------------------------------------------*
   PARAMETRES
 Par defaut: Format A4 portrait.
 *----------------------------------------------------------------------*/
// PARAMETRES IMPRIMANTE
// Papier imprimante (portrait)
var SheetH = 29.7;  // Hauteur de papier (cm)
var SheetW = 21.0;  // Largeur de papier (cm)

// Marges minimum de l'imprimante
/*
var PrintMargL = 0;  // Marge gauche (cm)
var PrintMargR = 0;  // Marge droite (cm)
var PrintMargT = 0;  // Marge haute (cm)
var PrintMargB = 0;  // Marge basse (cm)
*/
var PrintMargL = 0.6;  // Marge gauche (cm)
var PrintMargR = 0.68;  // Marge droite (cm)
var PrintMargT = 0.6;  // Marge haute (cm)
var PrintMargB = 0.6;  // Marge basse (cm)

// PARAMETRES D'IMAGE
// Marges deja autour de l'image
// que l'on peut ne pas imprimer.
var ImgMargL = 0;  // Marge gauche (cm)
var ImgMargR = 0;  // Marge droite (cm)
var ImgMargT = 0;  // Marge haute (cm)
var ImgMargB = 0;  // Marge basse (cm)
/*
var ImgMargL = 0.8;  // Marge gauche (cm)
var ImgMargR = 0.8;  // Marge droite (cm)
var ImgMargT = 0.0;  // Marge haute (cm)
var ImgMargB = 0.5;  // Marge basse (cm)
*/
// Modes
var ImgModeFrame = true; // Imprimer un cadre autour de l'image
/*----------------------------------------------------------------------*/
// PARAMETRES DIVERS

// Rognage max de l'image pour economie de papier
var CropMax = 1.0;  // %

// Couleur de fond (si pas transparent): blanc
backgroundColor.rgb.hexValue = 'FFFFFF';
/*----------------------------------------------------------------------*
   Globals
 *----------------------------------------------------------------------*/
var DocMain;  // Document principal
var HistBack = 0; // Nb of History back to do
/************************************************************************
   HISTORY
 ************************************************************************/
function history_Back() {
  var idnull = charIDToTypeID( "null" );
  var idslct = charIDToTypeID( "slct" );
  var idHstS = charIDToTypeID( "HstS" );
  var idOrdn = charIDToTypeID( "Ordn" );
  var idPrvs = charIDToTypeID( "Prvs" );
  var AD = new ActionDescriptor();
  var AR = new ActionReference();
  AR.putEnumerated( idHstS, idOrdn, idPrvs );
  AD.putReference( idnull, AR );
  executeAction( idslct, AD, DialogModes.NO );
};
/************************************************************************
                        DRAW
 ************************************************************************/
function PathFillWhite()
{
  // WARNING: Si path vide => erreur : "Abandon par utilisateur"
  var idnull  = charIDToTypeID( "null" );
  var idFl    = charIDToTypeID( "Fl  " );
  var idPath  = charIDToTypeID( "Path" );
  var idOrdn  = charIDToTypeID( "Ordn" );
  var idTrgt  = charIDToTypeID( "Trgt" );
  var idWhPt  = charIDToTypeID( "WhPt" );
  var idUsng  = charIDToTypeID( "Usng" );
  var idFlCn  = charIDToTypeID( "FlCn" );
  var idWht   = charIDToTypeID( "Wht " );
  var idOpct  = charIDToTypeID( "Opct" );
  var idPrc   = charIDToTypeID( "#Prc" );
  var idMd    = charIDToTypeID( "Md  " );
  var idBlnM  = charIDToTypeID( "BlnM" );
  var idNrml  = charIDToTypeID( "Nrml" );
  var idRds   = charIDToTypeID( "Rds " );
  var idPxl   = charIDToTypeID( "#Pxl" );
  var idAntA  = charIDToTypeID( "AntA" );
 
  var AC = new ActionDescriptor();
  var AR = new ActionReference();
  AR.putEnumerated( idPath, idOrdn, idTrgt );
  AC.putReference( idnull, AR );
  AC.putBoolean( idWhPt, true );
  AC.putEnumerated( idUsng, idFlCn, idWht );
  AC.putUnitDouble( idOpct, idPrc, 100.000000 );
  AC.putEnumerated( idMd, idBlnM, idNrml );
  AC.putUnitDouble( idRds, idPxl, 1.000000 );
  AC.putBoolean( idAntA, true );
  executeAction( idFl, AC, DialogModes.NO );
  HistBack++;
}
/*----------------------------------------------------------------------*
                        Draw Rect
 *----------------------------------------------------------------------*/
function RectDrawWhite(doc, Resol, x, y, w, h, ep)
{
  var line = new Array(new PathPointInfo,new PathPointInfo,
                       new PathPointInfo,new PathPointInfo);
  var line2= new Array(new PathPointInfo,new PathPointInfo,
                       new PathPointInfo,new PathPointInfo);
  var subPath = new Array(new SubPathInfo, new SubPathInfo);
  var path;
 
  // Convert
  var r  = Resol /72.0;
  x = Math.round(x/r);
  y = Math.round(y/r);
  h = Math.round(h/r);
  w = Math.round(w/r);
  ep= Math.round(ep/r);
  // WARNING: Si path vide => erreur : "Abandon par utilisateur"
  if (ep < 1) ep = 1;
 
  line[0].kind   = PointKind.CORNERPOINT;
  line[0].anchor  = new Array(x, y);
  line[0].leftDirection  = line[0].anchor;
  line[0].rightDirection = line[0].anchor;
 
  line[1].kind   = PointKind.CORNERPOINT;
  line[1].anchor  = new Array(x+w, y);
  line[1].leftDirection  = line[1].anchor;
  line[1].rightDirection = line[1].anchor;
 
  line[2].kind   = PointKind.CORNERPOINT;
  line[2].anchor  = new Array(x+w, y+h);
  line[2].leftDirection  = line[2].anchor;
  line[2].rightDirection = line[2].anchor;
 
  line[3].kind   = PointKind.CORNERPOINT;
  line[3].anchor  = new Array(x, y+h);
  line[3].leftDirection  = line[3].anchor;
  line[3].rightDirection = line[3].anchor;
 
  subPath[0].operation = ShapeOperation.SHAPEADD;
  subPath[0].closed = true;
  subPath[0].entireSubPath = line;
 
  line2[0].kind   = PointKind.CORNERPOINT;
  line2[0].anchor  = new Array(x+ep, y+ep);
  line2[0].leftDirection = line2[0].anchor;
  line2[0].rightDirection = line2[0].anchor;
 
  line2[1].kind   = PointKind.CORNERPOINT;
  line2[1].anchor  = new Array(x+w-ep, y+ep);
  line2[1].leftDirection = line2[1].anchor;
  line2[1].rightDirection = line2[1].anchor;
 
  line2[2].kind   = PointKind.CORNERPOINT;
  line2[2].anchor  = new Array(x+w-ep, y+h-ep);
  line2[2].leftDirection = line2[2].anchor;
  line2[2].rightDirection = line2[2].anchor;
 
  line2[3].kind   = PointKind.CORNERPOINT;
  line2[3].anchor  = new Array(x+ep, y+h-ep);
  line2[3].leftDirection = line2[3].anchor;
  line2[3].rightDirection = line2[3].anchor;
 
  subPath[1].operation = ShapeOperation.SHAPESUBTRACT;
  subPath[1].closed = true;
  subPath[1].entireSubPath = line2;
 
  path = doc.pathItems.add("RectWhite", subPath);
  HistBack+=2;
  PathFillWhite();
  path.remove();
  HistBack++;
 
  return(0);
}
/************************************************************************
   Main
 ************************************************************************/
try{
 
  var H,W, HV, WV, HH, WH;
  var CropArea = new Array(); // L,T,R,B
  var Resol, CmToPx;
  var SH, SW;   // Sheet format (px)
  var PH, PW;   // Printed area inside a sheet (px)
  var ML,MT,MB,MR;  // Printer Margins (px)
  var IL,IT,IB,IR;  // Image Margins (px)
  var RH, RW;
  var CL,CT,CW,CH;  // Crop area
  var PN;   // Piece number
  var RCWH, RCHH, RCWV, RCHV;
  var RCW, RCH;   // Total printed area without margins
  var SurfV, SurfH;  // Surfaces
  var LD,LC;   // Layers
  var NFirstL;   // not first layer
  var Ep;
 
  DocMain = activeDocument;
  if (DocMain.activeLayer != DocMain.layers[0]) NFirstL = true;
  else              NFirstL = false;
 
  H = Math.floor(DocMain.height);
  W = Math.floor(DocMain.width);
  Resol = DocMain.resolution;
  CmToPx = Resol / 2.54;
 
  // Print format
  SH = Math.floor(SheetH * CmToPx);
  SW = Math.floor(SheetW * CmToPx);
  ML = Math.floor(PrintMargL * CmToPx);
  MT = Math.floor(PrintMargT * CmToPx);
  MB = Math.floor(PrintMargB * CmToPx);
  MR = Math.floor(PrintMargR * CmToPx);
 
  IL = Math.floor(ImgMargL * CmToPx);
  IT = Math.floor(ImgMargT * CmToPx);
  IB = Math.floor(ImgMargB * CmToPx);
  IR = Math.floor(ImgMargR * CmToPx);
 
  if (IL+IR >= W || IT+IB >= H){
    alert("ERREUR: Marges d'image trop grandes !",ModName);
  }
  // Remove document margins
  if (IB || IR) {
    DocMain.resizeCanvas(W-IR, H-IB,
                         AnchorPosition.TOPLEFT);
    HistBack++;
    W -= IR;
    H -= IB;
  }
  if (IL || IT) {
    DocMain.resizeCanvas(W-IL, H-IT,
                         AnchorPosition.BOTTOMRIGHT);
    HistBack++;
    W -= IL;
    H -= IT;
  }
 
  // Printed area on one sheet
  PW = SW-ML-MR;
  PH = SH-MT-MB;
  //alert("Doc:H="+H+",W="+W+",Area:PH="+PH+",PW="+PW+",Resol="+Resol);
 
  // Choix Portrait(Vertical)/Paysage(Horizontal)
  // Surface en decoupage mode portrait
  HV = H;
  WV = W;
  RCWV = (Math.floor(WV/PW)+(WV % PW ? 1: 0))*PW;
  if ((WV % PW) && (WV % PW) <= WV*CropMax/100) {
    if (confirm("ATTENTION: En Portrait, seulement "+(WV % PW)+" Px de trop en Largeur.\nCouper pour economie de papier ?",
                false, ModName)) {
      RCWV = Math.floor(WV/PW)*PW;
      WV = RCWV;
    }
  }
  RCHV = (Math.floor(HV/PH)+(HV % PH ? 1: 0))*PH;
  if ((HV % PH) && (HV % PH) <= HV*CropMax/100) {
    if (confirm("ATTENTION: En portrait, seulement "+(HV % PH)+" Px de trop en Hauteur.\nCouper pour economie de papier ?",
                false, ModName)) {
      RCHV = Math.floor(HV/PH)*PH;
      HV = RCHV;
    }
  }
  SurfV = (RCHV + MT + MB) *
          (RCWV + ML + MR);
 
  // Surface en decoupage mode paysage
  // Doc is rotated -90dg
  WH = H;
  HH = W;
  RCHH = (Math.floor(HH/PH)+(HH % PH ? 1: 0))*PH;
  if ((HH % PH) && (HH % PH) <= HH*CropMax/100) {
    if (confirm("ATTENTION: En Paysage seulement "+(HH % PH)+" Px de trop en Largeur.\nCouper pour economie de papier ?",
                false, ModName)) {
      RCHH = Math.floor(HH/PH)*PH;
      HH = RCHH;
    }
  }
  RCWH = (Math.floor(WH/PW)+(WH % PW ? 1: 0))*PW;
  if ((WH % PW) && (WH % PW) <= WH*CropMax/100) {
    if (confirm("ATTENTION: En Paysage seulement "+(WH % PW)+" Px de trop en Hauteur.\nCouper pour economie de papier ?",
                false, ModName)) {
      RCWH = Math.floor(WH/PW)*PW;
      WH = RCWH;
    }
  }
  SurfH = (RCHH + MT + MB) *
          (RCWH + ML + MR);
 
  if (SurfV <= SurfH) {
    //alert("Decoupage optimal Portrait");
    RCW = RCWV;
    RCH = RCHV;
    // Ici ajuster Ix
    H   = HV;
    W   = WV;
  } else {
    //alert("Decoupage optimal Paysage");
    DocMain.rotateCanvas(-90);
    HistBack++;
    RCW = RCWH;
    RCH = RCHH;
    // Ici ajuster Ix
    // + rotation Ix
    H = IL; IL = IT; IT = IR; IR = IB; IB = H;
    H   = HH;
    W   = WH;
  }
  // Centrage
  DocMain.resizeCanvas((W + RCW)/2 + MR,
                       (H + RCH)/2 + MB,
                       AnchorPosition.TOPLEFT);
  HistBack++;
  DocMain.resizeCanvas(RCW + MR + ML,
                       RCH + MB + MT,
                       AnchorPosition.BOTTOMRIGHT);
  HistBack++;
 
  if (ImgModeFrame) {
    // Cadre autour de l'image originale
    LC = DocMain.artLayers.add();
    LC.name = "Cadre";
    LC.blendMode = BlendMode.DIFFERENCE;
    HistBack += 3;
    Ep = Math.floor((H > W ? H : W)/1000);
    if (Ep < 1) Ep = 1;
    RectDrawWhite(DocMain,Resol,ML-IL-Ep+((RCW-W)/2),
                                MT-IT-Ep+((RCH-H)/2),
                                W+IL+IR+Ep,H+IT+IB+Ep,Ep);
  }
  // Draw layer de decoupage
  LD = DocMain.artLayers.add();
  LD.name = "Zones d'impression";
  LD.blendMode = BlendMode.DIFFERENCE;
  HistBack += 3;
  Ep = Math.floor((H > W ? H : W)/1000);
  if (Ep < 2) Ep = 2;
  CL = 0; 
  CT = 0;
  CW = SW;
  CH = SH;
  while(CT < H) {
    while(CL < W) {
      RectDrawWhite(DocMain,Resol, CL+ML,CT+MT,PW,PH,Ep);
      CL += PW;
    } // while
    CT += PH;
    CL  = 0;
  } // while
 
  if (confirm("Imprimer ce Decoupage ?\n(Sinon modifier la taille de l'image)",
              false, ModName)) {
    LD.visible = false;
    PN = 0;
    CL = 0;  CT = 0;
    CW = SW; CH = SH;
    while(CT < H) {
      while(CL < W) {
        PN++;
        CropArea[0] = CL;
        CropArea[1] = CT;
        CropArea[2] = CL+CW;
        CropArea[3] = CT+CH;
        DocMain.crop(CropArea);
        DocMain.print();
        history_Back();
        CL += PW;
      } // while
      CT += PH;
      CL  = 0;
    } // while
  }
} catch(ex) {
  alert(ex.message, ModName);
  /*
  if (confirm("ERREUR: "+ ex.message +
              "\n Stop for debug ?", false, ModName)) {
    HistBack = 0;
    NFirstL  = false;
  }
  */
}
for (;HistBack;HistBack--) history_Back();
if (NFirstL) history_Back();  // Dont ask why!!!

preferences.rulerUnits = RulerUnits;
backgroundColor.rgb.hexValue = BGColor;

Partager cette page

Repost 0
Published by