首页 文章

使用PDShadingType4 Apache pdf框实现Type 4着色

提问于
浏览
1

我一直在尝试使用apache pdf框创建一个pdf三角形 . 使用PDShadingType4类 . 下面是代码实现,但它只创建了空pdf . 我没有在apache中提供的示例中找到任何PDShadingType4的实现 .

生成的三角形应该看起来像pdf在link左下角的三角形,可以在apache pdf框中找到issue

我无法使用PDShadingType4找到任何着色示例 .

以下实施是否正确?或者它们是使用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");
        }
    }

1 回答

  • 2

    此代码在左下角创建一个Gouraud阴影三角形:

    // 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();
    

    运行着色,调用

    contentStream.shadingFill(gouraudShading);
    

    这是一个不同的解码数组,类似于你链接到的示例PDF中的解码数组,尽管我只使用了16位而不是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);
    

    然后三角形的坐标为0x8000 0x8000,0x8100 0x8100,0x8200 0x8000 .

相关问题