コード例 #1
0
        private void CopyIndexedMemoryBitmap(int bits /*, ref bool hasAlpha*/, ImageDataBitmap dest)
        {
            int  firstMaskColor = -1, lastMaskColor = -1;
            bool segmentedColorMask = false;

            int bytesColorPaletteOffset = ((ImagePrivateDataBitmap)Image.Data).ColorPaletteOffset; // GDI+ always returns Windows bitmaps: sizeof BITMAPFILEHEADER + sizeof BITMAPINFOHEADER

            int  bytesFileOffset = ((ImagePrivateDataBitmap)Image.Data).Offset;
            uint paletteColors   = Image.Information.ColorsUsed;
            int  width           = (int)Image.Information.Width;
            int  height          = (int)Image.Information.Height;

            MonochromeMask mask = new MonochromeMask(width, height);

            bool isGray    = bits == 8 && (paletteColors == 256 || paletteColors == 0);
            int  isBitonal = 0; // 0: false; >0: true; <0: true (inverted)

            byte[] paletteData = new byte[3 * paletteColors];
            for (int color = 0; color < paletteColors; ++color)
            {
                paletteData[3 * color]     = Data[bytesColorPaletteOffset + 4 * color + 2];
                paletteData[3 * color + 1] = Data[bytesColorPaletteOffset + 4 * color + 1];
                paletteData[3 * color + 2] = Data[bytesColorPaletteOffset + 4 * color + 0];
                if (isGray)
                {
                    isGray = paletteData[3 * color] == paletteData[3 * color + 1] &&
                             paletteData[3 * color] == paletteData[3 * color + 2];
                }

                if (Data[bytesColorPaletteOffset + 4 * color + 3] < 128)
                {
                    // We treat this as transparency:
                    if (firstMaskColor == -1)
                    {
                        firstMaskColor = color;
                    }
                    if (lastMaskColor == -1 || lastMaskColor == color - 1)
                    {
                        lastMaskColor = color;
                    }
                    if (lastMaskColor != color)
                    {
                        segmentedColorMask = true;
                    }
                }
                //else
                //{
                //  // We treat this as opacity:
                //}
            }

            if (bits == 1)
            {
                if (paletteColors == 0)
                {
                    isBitonal = 1;
                }
                if (paletteColors == 2)
                {
                    if (paletteData[0] == 0 &&
                        paletteData[1] == 0 &&
                        paletteData[2] == 0 &&
                        paletteData[3] == 255 &&
                        paletteData[4] == 255 &&
                        paletteData[5] == 255)
                    {
                        isBitonal = 1; // Black on white
                    }
                    if (paletteData[5] == 0 &&
                        paletteData[4] == 0 &&
                        paletteData[3] == 0 &&
                        paletteData[2] == 255 &&
                        paletteData[1] == 255 &&
                        paletteData[0] == 255)
                    {
                        isBitonal = -1; // White on black
                    }
                }
            }

            // NYI: (no sample found where this was required)
            // if (segmentedColorMask = true)
            // { ... }

            bool isFaxEncoding = false;

            byte[] imageData    = new byte[((width * bits + 7) / 8) * height];
            byte[] imageDataFax = null;
            int    k            = 0;


            if (bits == 1 && dest._document.Options.EnableCcittCompressionForBilevelImages)
            {
                // TODO: flag/option?
                // We try Group 3 1D and Group 4 (2D) encoding here and keep the smaller byte array.
                //byte[] temp = new byte[imageData.Length];
                //int ccittSize = DoFaxEncoding(ref temp, imageBits, (uint)bytesFileOffset, (uint)width, (uint)height);

                // It seems that Group 3 2D encoding never beats both other encodings, therefore we don't call it here.
                //byte[] temp2D = new byte[imageData.Length];
                //uint dpiY = (uint)image.VerticalResolution;
                //uint kTmp = 0;
                //int ccittSize2D = DoFaxEncoding2D((uint)bytesFileOffset, ref temp2D, imageBits, (uint)width, (uint)height, dpiY, out kTmp);
                //k = (int) kTmp;

                byte[] tempG4      = new byte[imageData.Length];
                int    ccittSizeG4 = PdfImage.DoFaxEncodingGroup4(ref tempG4, Data, (uint)bytesFileOffset, (uint)width, (uint)height);

                isFaxEncoding = /*ccittSize > 0 ||*/ ccittSizeG4 > 0;
                if (isFaxEncoding)
                {
                    //if (ccittSize == 0)
                    //  ccittSize = 0x7fffffff;
                    if (ccittSizeG4 == 0)
                    {
                        ccittSizeG4 = 0x7fffffff;
                    }
                    //if (ccittSize <= ccittSizeG4)
                    //{
                    //  Array.Resize(ref temp, ccittSize);
                    //  imageDataFax = temp;
                    //  k = 0;
                    //}
                    //else
                    {
                        Array.Resize(ref tempG4, ccittSizeG4);
                        imageDataFax = tempG4;
                        k            = -1;
                    }
                }
            }

            //if (!isFaxEncoding)
            {
                int bytesOffsetRead = 0;
                if (bits == 8 || bits == 4 || bits == 1)
                {
                    int bytesPerLine = (width * bits + 7) / 8;
                    for (int y = 0; y < height; ++y)
                    {
                        mask.StartLine(y);
                        int bytesOffsetWrite = (height - 1 - y) * ((width * bits + 7) / 8);
                        for (int x = 0; x < bytesPerLine; ++x)
                        {
                            if (isGray)
                            {
                                // Lookup the gray value from the palette:
                                imageData[bytesOffsetWrite] = paletteData[3 * Data[bytesFileOffset + bytesOffsetRead]];
                            }
                            else
                            {
                                // Store the palette index.
                                imageData[bytesOffsetWrite] = Data[bytesFileOffset + bytesOffsetRead];
                            }
                            if (firstMaskColor != -1)
                            {
                                int n = Data[bytesFileOffset + bytesOffsetRead];
                                if (bits == 8)
                                {
                                    // TODO???: segmentedColorMask == true => bad mask NYI
                                    mask.AddPel((n >= firstMaskColor) && (n <= lastMaskColor));
                                }
                                else if (bits == 4)
                                {
                                    // TODO???: segmentedColorMask == true => bad mask NYI
                                    int n1 = (n & 0xf0) / 16;
                                    int n2 = (n & 0x0f);
                                    mask.AddPel((n1 >= firstMaskColor) && (n1 <= lastMaskColor));
                                    mask.AddPel((n2 >= firstMaskColor) && (n2 <= lastMaskColor));
                                }
                                else if (bits == 1)
                                {
                                    // TODO???: segmentedColorMask == true => bad mask NYI
                                    for (int bit = 1; bit <= 8; ++bit)
                                    {
                                        int n1 = (n & 0x80) / 128;
                                        mask.AddPel((n1 >= firstMaskColor) && (n1 <= lastMaskColor));
                                        n *= 2;
                                    }
                                }
                            }
                            bytesOffsetRead  += 1;
                            bytesOffsetWrite += 1;
                        }
                        bytesOffsetRead = 4 * ((bytesOffsetRead + 3) / 4); // Align to 32 bit boundary
                    }
                }
                else
                {
                    throw new NotImplementedException("ReadIndexedMemoryBitmap: unsupported format #3");
                }
            }

            dest.Data   = imageData;
            dest.Length = imageData.Length;

            if (imageDataFax != null)
            {
                dest.DataFax   = imageDataFax;
                dest.LengthFax = imageDataFax.Length;
            }

            dest.IsGray    = isGray;
            dest.K         = k;
            dest.IsBitonal = isBitonal;

            dest.PaletteData        = paletteData;
            dest.PaletteDataLength  = paletteData.Length;
            dest.SegmentedColorMask = segmentedColorMask;

            //if (alphaMask != null)
            //{
            //    dest.AlphaMask = alphaMask;
            //    dest.AlphaMaskLength = alphaMask.Length;
            //}

            if (mask != null && firstMaskColor != -1)
            {
                dest.BitmapMask       = mask.MaskData;
                dest.BitmapMaskLength = mask.MaskData.Length;
            }
        }