2017-05-03 1 views
0

J'ai essayé de créer un triangle en pdf en utilisant la boîte de pdf apache. Utilisation de la classe PDShadingType4. Ci-dessous l'implémentation du code mais elle n'a créé que des pdf vides. Je n'ai trouvé aucune implémentation de PDShadingType4 dans les exemples fournis dans apache.Implémenter type 4 shadings en utilisant PDShadingType4 Apache pdf box

Le triangle généré devrait ressembler le triangle en bas à gauche du pdf à link qui se trouve dans la boîte pdf apache issue

Je ne suis pas en mesure de trouver un exemple d'ombrage à l'aide PDShadingType4.

L'implémentation ci-dessous est-elle correcte? ou leur est une autre façon d'obtenir ombrage (triangulaire) en utilisant PDShadingType4

 

    import java.io.IOException; 
    import org.apache.pdfbox.cos.COSArray; 
    import org.apache.pdfbox.cos.COSFloat; 
    import org.apache.pdfbox.cos.COSInteger; 
    import org.apache.pdfbox.cos.COSName; 
    import org.apache.pdfbox.cos.COSStream; 
    import org.apache.pdfbox.pdmodel.PDDocument; 
    import org.apache.pdfbox.pdmodel.PDPage; 
    import org.apache.pdfbox.pdmodel.PDPageContentStream; 
    import org.apache.pdfbox.pdmodel.common.function.PDFunctionType2; 
    import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB; 
    import org.apache.pdfbox.pdmodel.graphics.shading.PDShading; 
    import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType4; 

    public class TriangleGraident2 { 

     public void create(String file) throws IOException { 
      PDDocument document = null; 
      try { 
       document = new PDDocument(); 
       PDPage page = new PDPage(); 
       document.addPage(page); 

       PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, false); 

       contentStream.moveTo(38, 17); 

       COSStream fdict = new COSStream(); 
       fdict.setInt(COSName.FUNCTION_TYPE, 2); 

       COSArray cosArray = new COSArray(); 
       cosArray.add(COSInteger.get(104)); 
       cosArray.add(COSInteger.get(83)); 
       cosArray.add(COSInteger.get(170)); 
       cosArray.add(COSInteger.get(17)); 
       cosArray.add(COSInteger.get(38)); 
       cosArray.add(COSInteger.get(17)); 


       /*Setting color */ 
       COSArray c0 = new COSArray(); 
       c0.add(COSFloat.get("1")); 
       c0.add(COSFloat.get("0")); 
       c0.add(COSFloat.get("0")); 
       COSArray c1 = new COSArray(); 
       c1.add(COSFloat.get("0.5")); 
       c1.add(COSFloat.get("1")); 
       c1.add(COSFloat.get("0.5")); 
       /*Setting color*/ 


       COSArray decode = new COSArray(); 
       decode.add(COSFloat.get("0.0")); 
       decode.add(COSFloat.get("1.0")); 
       decode.add(COSFloat.get("0.0")); 
       decode.add(COSFloat.get("1.0")); 
       decode.add(COSFloat.get("0.0")); 

       fdict.setItem(COSName.C0, c0); 
       fdict.setItem(COSName.C1, c1); 

       PDFunctionType2 func = new PDFunctionType2(fdict); 
       PDShadingType4 shading = new PDShadingType4(fdict); 
       shading.setColorSpace(PDDeviceRGB.INSTANCE); 
       shading.setShadingType(PDShading.SHADING_TYPE4); 

       shading.getCOSObject().setInt(COSName.LENGTH, 32); 

       shading.setBitsPerCoordinate(24); 
       shading.setBitsPerComponent(16); 
       shading.setBitsPerFlag(8); 
       shading.getCOSObject().setItem(COSName.COORDS, cosArray); 
       shading.setDecodeValues(decode); 
       shading.setFunction(func); 
       contentStream.shadingFill(shading); 
       contentStream.close(); 
       document.save(file); 
       document.close(); 

      } 
      finally { 
       if (document != null) { 
        document.close(); 
       } 
      } 
     } 

     public static void main(String[] args) throws IOException { 
      TriangleGraident2 creator = new TriangleGraident2(); 
      creator.create("C:\\Users\\abc\\Desktop\\triangle_image.pdf"); 
     } 
    } 

+0

Par coïncidence, c'est moi qui ai créé l'ombrage avec lequel vous liez, mais avec PostScript, puis je l'ai converti en PDF avec ghostscript. Avez-vous vraiment besoin de shadings de type 4? Et pas de type 2 (Axial) ou de type 3 (radial)? Parce que ces deux-là ont un exemple dans le code source de PDFBox, et les ombrages de type 4 ne le font pas, parce que c'est si difficile ... Les nuances de type 4 sont des triangles comme celui que vous mentionnez. Habituellement, vous en auriez des tonnes, pour créer une illusion 3D. Votre code manque le flux. Voir dans la spécification PDF ... il contient des couleurs, des coordonnées et des drapeaux. Des trucs très délicats. –

+0

Vous n'avez pas non plus besoin de la fonction, il n'est pas nécessaire, vous pouvez obtenir plus de triangles colorés en ne l'utilisant pas. (Parce que si vous utilisez des fonctions, chaque bord d'un triangle aurait une valeur de 1, qui serait ensuite transformée en n composants de couleur par la fonction, il est donc difficile d'obtenir 3 "extrêmes"). Le contenu du flux est f x y c1 ... cn, voir p190 de la spécification. Je pourrais probablement implémenter une démo si vous êtes vraiment sûr que vous en avez besoin. –

+0

Oui Monsieur J'ai besoin d'ombrage de type 4. J'ai également essayé l'ombrage de type 4 après avoir lu la spécification pdf que vous avez mentionnée dans le lien que vous avez créé.mais il est difficile de trouver le lien ou la documentation du triangle. Pouvez-vous s'il vous plaît corriger le code ci-dessus ou fournir le lien vers le code pour le triangle que vous avez créé.Il me sera très utile.Je pense que nous ne pourrons pas créer de triangle en utilisant le type 2 (Axial) ou le type 3 (radial) ombrage. Et après cela, j'ai aussi besoin de dessiner polygone.Alors je travaillais avec ombrage Type 4 – user3194123

Répondre

2

Ce code crée un triangle ombré Gouraud en bas à gauche:

// See PDF 32000 specification, 
// 8.7.4.5.5 Type 4 Shadings (Free-Form Gouraud-Shaded Triangle Meshes) 
PDShadingType4 gouraudShading = new PDShadingType4(new COSStream()); 
gouraudShading.setShadingType(PDShading.SHADING_TYPE4); 
// we use multiple of 8, so that no padding is needed 
gouraudShading.setBitsPerFlag(8); 
gouraudShading.setBitsPerCoordinate(16); 
gouraudShading.setBitsPerComponent(8); 
COSArray decodeArray = new COSArray(); 
// coordinates x y map 16 bits 0..FFFF to 0..FFFF to make your life easy 
// so no calculation is needed, but you can only use integer coordinates 
// for real numbers, you'll need smaller bounds, e.g. 0xFFFF/0xA = 0x1999 
// would allow 1 point decimal result coordinate. 
// See in PDF specification: 8.9.5.2 Decode Arrays 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.get(0xFFFF)); 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.get(0xFFFF)); 
// colors r g b map 8 bits from 0..FF to 0..1 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
gouraudShading.setDecodeValues(decodeArray); 
gouraudShading.setColorSpace(PDDeviceRGB.INSTANCE); 

// Function is not required for type 4 shadings and not really useful, 
// because if a function would be used, each edge "color" of a triangle would be one value, 
// which would then transformed into n color components by the function so it is 
// difficult to get 3 "extremes". 

OutputStream os = ((COSStream) gouraudShading.getCOSObject()).createOutputStream(); 
MemoryCacheImageOutputStream mcos = new MemoryCacheImageOutputStream(os); 

// Vertex 1, starts with flag1 
// (flags always 0 for vertices of start triangle) 
mcos.writeByte(0); 
// x1 y1 (left corner) 
mcos.writeShort(0); 
mcos.writeShort(0); 
// r1 g1 b1 (red) 
mcos.writeByte(0xFF); 
mcos.writeByte(0); 
mcos.writeByte(0); 

// Vertex 2, starts with flag2 
mcos.writeByte(0); 
// x2 y2 (top corner) 
mcos.writeShort(100); 
mcos.writeShort(100); 
// r2 g2 b2 (green) 
mcos.writeByte(0); 
mcos.writeByte(0xFF); 
mcos.writeByte(0); 

// Vertex 3, starts with flag3 
mcos.writeByte(0); 
// x3 y3 (right corner) 
mcos.writeShort(200); 
mcos.writeShort(0); 
// r3 g3 b3 (blue) 
mcos.writeByte(0); 
mcos.writeByte(0); 
mcos.writeByte(0xFF); 

mcos.close(); 
// outside stream MUST be closed as well, see javadoc of MemoryCacheImageOutputStream 
os.close(); 

pour exécuter l'ombrage, appelez

contentStream.shadingFill(gouraudShading); 

Gouraud shaded triangle

Voici un tableau de décodage différent, similaire à celle de l'exemple PDF vous un lien, bien que je ne 16 bits au lieu de 24:

COSArray decodeArray = new COSArray(); 
// coordinates x y map 16 bits 0..FFFF to -16384..16384 
// this means that 0x8000 maps to 0 
// some other useful values 
// - 0x862C maps to top of A4 page 
// - 0x84C4 maps to right of A4 page 
// - 0x8262 maps to horizontal middle of A4 page 
decodeArray.add(COSInteger.get(-16384)); 
decodeArray.add(COSInteger.get(16384)); 
decodeArray.add(COSInteger.get(-16384)); 
decodeArray.add(COSInteger.get(16384)); 
// colors r g b map 8 bits from 0..FF to 0..1 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
decodeArray.add(COSInteger.ZERO); 
decodeArray.add(COSInteger.ONE); 
gouraudShading.setDecodeValues(decodeArray); 

Les coordonnées du triangle serait alors 0x8000 0x8000, 0x8100 0x8100, 0x8200 0x8000.

+0

Merci Monsieur, Ce fut une aide précieuse. – user3194123