Exemplo n.º 1
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr44tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int rasterOffset1 = rasterOffset + width + rasterShift;
            int rasterOffset2 = rasterOffset1 + width + rasterShift;
            int rasterOffset3 = rasterOffset2 + width + rasterShift;
            int incr = 3 * width + 4 * rasterShift;

            // adjust bufferShift
            bufferShift = (bufferShift * 18) / 4;
            if ((height & 3) == 0 && (width & 3) == 0)
            {
                for (; height >= 4; height -= 4)
                {
                    x = width >> 2;
                    do
                    {
                        int Cb = buffer[offset + 16];
                        int Cr = buffer[offset + 17];

                        img.YCbCrtoRGB(out raster[rasterOffset], buffer[offset + 0], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 3], buffer[offset + 3], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset1 + 0], buffer[offset + 4], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset1 + 1], buffer[offset + 5], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset1 + 2], buffer[offset + 6], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset1 + 3], buffer[offset + 7], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 0], buffer[offset + 8], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 1], buffer[offset + 9], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 2], buffer[offset + 10], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 3], buffer[offset + 11], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset3 + 0], buffer[offset + 12], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset3 + 1], buffer[offset + 13], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset3 + 2], buffer[offset + 14], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset3 + 3], buffer[offset + 15], Cb, Cr);

                        rasterOffset += 4;
                        rasterOffset1 += 4;
                        rasterOffset2 += 4;
                        rasterOffset3 += 4;
                        offset += 18;
                    }
                    while (--x != 0);

                    rasterOffset += incr;
                    rasterOffset1 += incr;
                    rasterOffset2 += incr;
                    rasterOffset3 += incr;
                    offset += bufferShift;
                }
            }
            else
            {
                while (height > 0)
                {
                    for (x = width; x > 0; )
                    {
                        int Cb = buffer[offset + 16];
                        int Cr = buffer[offset + 17];

                        bool h_goOn = false;
                        bool x_goOn = false;

                        // order of if's is important
                        if (x < 1 || x > 3)
                        {
                            // order of if's is important
                            h_goOn = false;
                            if (height < 1 || height > 3)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset3 + 3], buffer[offset + 15], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 3 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 3], buffer[offset + 11], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 2 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset1 + 3], buffer[offset + 7], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 1 || h_goOn)
                                img.YCbCrtoRGB(out raster[rasterOffset + 3], buffer[offset + 3], Cb, Cr);

                            x_goOn = true;
                        }

                        if (x == 3 || x_goOn)
                        {
                            // order of if's is important
                            h_goOn = false;
                            if (height < 1 || height > 3)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset3 + 2], buffer[offset + 14], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 3 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 2], buffer[offset + 10], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 2 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset1 + 2], buffer[offset + 6], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 1 || h_goOn)
                                img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);

                            x_goOn = true;
                        }

                        if (x == 2 || x_goOn)
                        {
                            // order of if's is important
                            h_goOn = false;
                            if (height < 1 || height > 3)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset3 + 1], buffer[offset + 13], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 3 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 1], buffer[offset + 9], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 2 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset1 + 1], buffer[offset + 5], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 1 || h_goOn)
                                img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);
                        }

                        if (x == 1 || x_goOn)
                        {
                            // order of if's is important
                            h_goOn = false;
                            if (height < 1 || height > 3)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset3 + 0], buffer[offset + 12], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 3 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 0], buffer[offset + 8], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 2 || h_goOn)
                            {
                                img.YCbCrtoRGB(out raster[rasterOffset1 + 0], buffer[offset + 4], Cb, Cr);
                                h_goOn = true;
                            }

                            if (height == 1 || h_goOn)
                                img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                        }

                        if (x < 4)
                        {
                            rasterOffset += x;
                            rasterOffset1 += x;
                            rasterOffset2 += x;
                            rasterOffset3 += x;
                            x = 0;
                        }
                        else
                        {
                            rasterOffset += 4;
                            rasterOffset1 += 4;
                            rasterOffset2 += 4;
                            rasterOffset3 += 4;
                            x -= 4;
                        }

                        offset += 18;
                    }

                    if (height <= 4)
                        break;

                    height -= 4;
                    rasterOffset += incr;
                    rasterOffset1 += incr;
                    rasterOffset2 += incr;
                    rasterOffset3 += incr;
                    offset += bufferShift;
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get an tile-organized image that has
        /// SamplesPerPixel > 1
        /// PlanarConfiguration separated
        /// We assume that all such images are RGB.
        /// </summary>
        private static bool gtTileSeparate(TiffRgbaImage img, int[] raster, int offset, int width, int height)
        {
            int tilesize = img.tif.TileSize();
            byte[] buf = new byte[(img.alpha != 0 ? 4 : 3) * tilesize];

            int p0 = 0;
            int p1 = p0 + tilesize;
            int p2 = p1 + tilesize;
            int pa = (img.alpha != 0 ? (p2 + tilesize) : -1);

            FieldValue[] result = img.tif.GetField(TiffTag.TileWidth);
            int tileWidth = result[0].ToInt();

            result = img.tif.GetField(TiffTag.TileLength);
            int tileHeight = result[0].ToInt();

            int flip = img.setorientation();
            int y;
            int rasterShift;
            if ((flip & FLIP_VERTICALLY) != 0)
            {
                y = height - 1;
                rasterShift = -(tileWidth + width);
            }
            else
            {
                y = 0;
                rasterShift = -(tileWidth - width);
            }

            bool ret = true;
            for (int row = 0; row < height; )
            {
                int rowstoread = tileHeight - (row + img.row_offset) % tileHeight;
                int nrow = (row + rowstoread > height ? height - row : rowstoread);
                for (int col = 0; col < width; col += tileWidth)
                {
                    if (img.tif.ReadTile(buf, p0, col + img.col_offset, row + img.row_offset, 0, 0) < 0 && img.stoponerr)
                    {
                        ret = false;
                        break;
                    }

                    if (img.tif.ReadTile(buf, p1, col + img.col_offset, row + img.row_offset, 0, 1) < 0 && img.stoponerr)
                    {
                        ret = false;
                        break;
                    }

                    if (img.tif.ReadTile(buf, p2, col + img.col_offset, row + img.row_offset, 0, 2) < 0 && img.stoponerr)
                    {
                        ret = false;
                        break;
                    }

                    if (img.alpha != 0)
                    {
                        if (img.tif.ReadTile(buf, pa, col + img.col_offset, row + img.row_offset, 0, 3) < 0 && img.stoponerr)
                        {
                            ret = false;
                            break;
                        }
                    }

                    int pos = ((row + img.row_offset) % tileHeight) * img.tif.TileRowSize();

                    if (col + tileWidth > width)
                    {
                        // Tile is clipped horizontally.
                        // Calculate visible portion and skewing factors.
                        int npix = width - col;
                        int bufferShift = tileWidth - npix;

                        img.putSeparate(img, raster, offset + y * width + col, rasterShift + bufferShift,
                            col, y, npix, nrow,
                            buf, p0 + pos, p1 + pos, p2 + pos, img.alpha != 0 ? (pa + pos) : -1, bufferShift);
                    }
                    else
                    {
                        img.putSeparate(img, raster, offset + y * width + col, rasterShift,
                            col, y, tileWidth, nrow,
                            buf, p0 + pos, p1 + pos, p2 + pos, img.alpha != 0 ? (pa + pos) : -1, 0);
                    }
                }

                y += ((flip & FLIP_VERTICALLY) != 0 ? -nrow : nrow);
                row += nrow;
            }

            if ((flip & FLIP_HORIZONTALLY) != 0)
            {
                for (int line = 0; line < height; line++)
                {
                    int left = offset + line * width;
                    int right = left + width - 1;

                    while (left < right)
                    {
                        int temp = raster[left];
                        raster[left] = raster[right];
                        raster[right] = temp;
                        left++;
                        right--;
                    }
                }
            }

            return ret;
        }
Exemplo n.º 3
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr21tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            bufferShift = (bufferShift * 4) / 2;

            do
            {
                x = width >> 1;
                do
                {
                    int Cb = buffer[offset + 2];
                    int Cr = buffer[offset + 3];

                    img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                    img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);

                    rasterOffset += 2;
                    offset += 4;
                }
                while (--x != 0);

                if ((width & 1) != 0)
                {
                    int Cb = buffer[offset + 2];
                    int Cr = buffer[offset + 3];

                    img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);

                    rasterOffset += 1;
                    offset += 4;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
            while (--height != 0);
        }
Exemplo n.º 4
0
        /// <summary>
        /// 16-bit unpacked samples => RGBA w/ associated alpha
        /// </summary>
        private static void putRGBAAseparate16bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height,
            byte[] buffer, int offset1, int offset2, int offset3, int offset4, int bufferShift)
        {
            short[] wrgba = Tiff.ByteArrayToShorts(buffer, 0, buffer.Length);

            offset1 /= sizeof(short);
            offset2 /= sizeof(short);
            offset3 /= sizeof(short);
            offset4 /= sizeof(short);

            while (height-- > 0)
            {
                for (x = 0; x < width; x++)
                {
                    raster[rasterOffset] = PACKW4(wrgba[offset1], wrgba[offset2], wrgba[offset3], wrgba[offset4]);
                    rasterOffset++;
                    offset1++;
                    offset2++;
                    offset3++;
                    offset4++;
                }

                offset1 += bufferShift;
                offset2 += bufferShift;
                offset3 += bufferShift;
                offset4 += bufferShift;

                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ no subsampling => RGB
        /// </summary>
        private static void putseparate8bitYCbCr11tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height,
            byte[] buffer, int offset1, int offset2, int offset3, int offset4, int bufferShift)
        {
            while (height-- > 0)
            {
                x = width;
                do
                {
                    int r, g, b;
                    img.ycbcr.YCbCrtoRGB(buffer[offset1], buffer[offset2], buffer[offset3], out r, out g, out b);

                    raster[rasterOffset] = PACK(r, g, b);
                    rasterOffset++;
                    offset1++;
                    offset2++;
                    offset3++;
                } while (--x != 0);

                offset1 += bufferShift;
                offset2 += bufferShift;
                offset3 += bufferShift;
                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ no subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr11tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            bufferShift *= 3;
            do
            {
                x = width; // was x = w >> 1; patched 2000/09/25 [email protected]
                do
                {
                    int Cb = buffer[offset + 1];
                    int Cr = buffer[offset + 2];

                    img.YCbCrtoRGB(out raster[rasterOffset], buffer[offset + 0], Cb, Cr);
                    rasterOffset++;
                    offset += 3;
                }
                while (--x != 0);

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
            while (--height != 0);
        }
Exemplo n.º 7
0
        /// <summary>
        /// 8-bit unpacked samples => RGBA w/ associated alpha
        /// </summary>
        private static void putRGBAAseparate8bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height,
            byte[] buffer, int offset1, int offset2, int offset3, int offset4, int bufferShift)
        {
            while (height-- > 0)
            {
                int _x;
                for (_x = width; _x >= 8; _x -= 8)
                {
                    for (int rc = 0; rc < 8; rc++)
                    {
                        raster[rasterOffset] = PACK4(buffer[offset1], buffer[offset2], buffer[offset3], buffer[offset4]);
                        rasterOffset++;
                        offset1++;
                        offset2++;
                        offset3++;
                        offset4++;
                    }
                }

                if (_x > 0)
                {
                    if (_x <= 7 && _x > 0)
                    {
                        for (int i = _x; i > 0; i--)
                        {
                            raster[rasterOffset] = PACK4(buffer[offset1], buffer[offset2], buffer[offset3], buffer[offset4]);
                            rasterOffset++;
                            offset1++;
                            offset2++;
                            offset3++;
                            offset4++;
                        }
                    }
                }

                offset1 += bufferShift;
                offset2 += bufferShift;
                offset3 += bufferShift;
                offset4 += bufferShift;

                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// 2-bit greyscale => colormap/RGB
        /// </summary>
        private static void put2bitbwtile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int[][] BWmap = img.BWmap;
            bufferShift /= 4;

            while (height-- > 0)
            {
                int[] bw = null;

                int _x;
                for (_x = width; _x >= 4; _x -= 4)
                {
                    bw = BWmap[buffer[offset]];
                    offset++;
                    for (int rc = 0; rc < 4; rc++)
                    {
                        raster[rasterOffset] = bw[rc];
                        rasterOffset++;
                    }
                }

                if (_x > 0)
                {
                    bw = BWmap[buffer[offset]];
                    offset++;

                    if (_x <= 3 && _x > 0)
                    {
                        for (int i = 0; i < _x; i++)
                        {
                            raster[rasterOffset] = bw[i];
                            rasterOffset++;
                        }
                    }
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// 4-bit greyscale => colormap/RGB
        /// </summary>
        private static void put4bitbwtile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int[][] BWmap = img.BWmap;
            bufferShift /= 2;

            while (height-- > 0)
            {
                int[] bw = null;

                int _x;
                for (_x = width; _x >= 2; _x -= 2)
                {
                    bw = BWmap[buffer[offset]];
                    offset++;
                    for (int rc = 0; rc < 2; rc++)
                    {
                        raster[rasterOffset] = bw[rc];
                        rasterOffset++;
                    }
                }

                if (_x != 0)
                {
                    bw = BWmap[buffer[offset]];
                    offset++;

                    raster[rasterOffset] = bw[0];
                    rasterOffset++;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// 8-bit greyscale => colormap/RGB
        /// </summary>
        private static void putgreytile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            int[][] BWmap = img.BWmap;

            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    raster[rasterOffset] = BWmap[buffer[offset]][0];
                    rasterOffset++;
                    offset += samplesperpixel;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// 16-bit greyscale => colormap/RGB
        /// </summary>
        private static void put16bitbwtile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            int[][] BWmap = img.BWmap;

            while (height-- > 0)
            {
                short[] wp = Tiff.ByteArrayToShorts(buffer, offset, buffer.Length - offset);
                int wpPos = 0;

                for (x = width; x-- > 0; )
                {
                    // use high order byte of 16bit value
                    raster[rasterOffset] = BWmap[(wp[wpPos] & 0xffff) >> 8][0];
                    rasterOffset++;
                    offset += 2 * samplesperpixel;
                    wpPos += samplesperpixel;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// 1-bit palette => colormap/RGB
        /// </summary>
        private static void put1bitcmaptile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int[][] PALmap = img.PALmap;
            bufferShift /= 8;

            while (height-- > 0)
            {
                int[] bw;
                int bwPos = 0;

                int _x;
                for (_x = width; _x >= 8; _x -= 8)
                {
                    bw = PALmap[buffer[offset++]];
                    bwPos = 0;

                    for (int i = 0; i < 8; i++)
                        raster[rasterOffset++] = bw[bwPos++];
                }

                if (_x > 0)
                {
                    bw = PALmap[buffer[offset++]];
                    bwPos = 0;

                    if (_x <= 7 && _x > 0)
                    {
                        for (int i = 0; i < _x; i++)
                            raster[rasterOffset++] = bw[bwPos++];
                    }
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Get a strip-organized image with
        ///  SamplesPerPixel > 1
        ///  PlanarConfiguration separated
        /// We assume that all such images are RGB.
        /// </summary>
        private static bool gtStripSeparate(TiffRgbaImage img, int[] raster, int offset, int width, int height)
        {
            int stripsize = img.tif.StripSize();
            byte[] buf = new byte[(img.alpha != 0 ? 4 : 3) * stripsize];

            int p0 = 0;
            int p1 = p0 + stripsize;
            int p2 = p1 + stripsize;
            int pa = p2 + stripsize;
            pa = (img.alpha != 0 ? (p2 + stripsize) : -1);

            int flip = img.setorientation();
            int y;
            int rasterShift;
            if ((flip & FLIP_VERTICALLY) != 0)
            {
                y = height - 1;
                rasterShift = -(width + width);
            }
            else
            {
                y = 0;
                rasterShift = -(width - width);
            }

            FieldValue[] result = img.tif.GetFieldDefaulted(TiffTag.RowsPerStrip);
            int rowsperstrip = result[0].ToInt();

            int scanline = img.tif.ScanlineSize();
            int bufferShift = (width < img.width ? img.width - width : 0);
            bool ret = true;
            for (int row = 0; row < height; )
            {
                int rowstoread = rowsperstrip - (row + img.row_offset) % rowsperstrip;
                int nrow = (row + rowstoread > height ? height - row : rowstoread);
                int offset_row = row + img.row_offset;

                if (img.tif.ReadEncodedStrip(img.tif.ComputeStrip(offset_row, 0), buf, p0, ((row + img.row_offset) % rowsperstrip + nrow) * scanline) < 0 && img.stoponerr)
                {
                    ret = false;
                    break;
                }

                if (img.tif.ReadEncodedStrip(img.tif.ComputeStrip(offset_row, 1), buf, p1, ((row + img.row_offset) % rowsperstrip + nrow) * scanline) < 0 && img.stoponerr)
                {
                    ret = false;
                    break;
                }

                if (img.tif.ReadEncodedStrip(img.tif.ComputeStrip(offset_row, 2), buf, p2, ((row + img.row_offset) % rowsperstrip + nrow) * scanline) < 0 && img.stoponerr)
                {
                    ret = false;
                    break;
                }

                if (img.alpha != 0)
                {
                    if ((img.tif.ReadEncodedStrip(img.tif.ComputeStrip(offset_row, 3), buf, pa, ((row + img.row_offset) % rowsperstrip + nrow) * scanline) < 0 && img.stoponerr))
                    {
                        ret = false;
                        break;
                    }
                }

                int pos = ((row + img.row_offset) % rowsperstrip) * scanline;

                img.putSeparate(img, raster, offset + y * width, rasterShift,
                    0, y, width, nrow,
                    buf, p0 + pos, p1 + pos, p2 + pos, img.alpha != 0 ? (pa + pos) : -1, bufferShift);

                y += (flip & FLIP_VERTICALLY) != 0 ? -nrow : nrow;
                row += nrow;
            }

            if ((flip & FLIP_HORIZONTALLY) != 0)
            {
                for (int line = 0; line < height; line++)
                {
                    int left = offset + line * width;
                    int right = left + width - 1;

                    while (left < right)
                    {
                        int temp = raster[left];
                        raster[left] = raster[right];
                        raster[right] = temp;
                        left++;
                        right--;
                    }
                }
            }

            return ret;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Get a strip-organized image that has 
        /// PlanarConfiguration contiguous if SamplesPerPixel > 1
        ///  or
        /// SamplesPerPixel == 1
        /// </summary>
        private static bool gtStripContig(TiffRgbaImage img, int[] raster, int offset, int width, int height)
        {
            byte[] buf = new byte[img.tif.StripSize()];

            int flip = img.setorientation();
            int y;
            int rasterShift;
            if ((flip & FLIP_VERTICALLY) != 0)
            {
                y = height - 1;
                rasterShift = -(width + width);
            }
            else
            {
                y = 0;
                rasterShift = -(width - width);
            }

            FieldValue[] result = img.tif.GetFieldDefaulted(TiffTag.RowsPerStrip);
            int rowsperstrip = result[0].ToInt();
            if (rowsperstrip == -1)
            {
                // San Chen <*****@*****.**>
                // HACK: should be UInt32.MaxValue
                rowsperstrip = Int32.MaxValue;
            }

            result = img.tif.GetFieldDefaulted(TiffTag.YCBCRSUBSAMPLING);
            short subsamplingver = result[1].ToShort();

            int scanline = img.tif.newScanlineSize();
            int bufferShift = (width < img.width ? img.width - width : 0);
            bool ret = true;

            for (int row = 0; row < height; )
            {
                int rowstoread = rowsperstrip - (row + img.row_offset) % rowsperstrip;
                int nrow = (row + rowstoread > height ? height - row : rowstoread);
                int nrowsub = nrow;
                if ((nrowsub % subsamplingver) != 0)
                    nrowsub += subsamplingver - nrowsub % subsamplingver;

                if (img.tif.ReadEncodedStrip(img.tif.ComputeStrip(row + img.row_offset, 0), buf, 0, ((row + img.row_offset) % rowsperstrip + nrowsub) * scanline) < 0 && img.stoponerr)
                {
                    ret = false;
                    break;
                }

                int pos = ((row + img.row_offset) % rowsperstrip) * scanline;
                img.putContig(img, raster, offset + y * width, rasterShift, 0, y, width, nrow, buf, pos, bufferShift);
                y += (flip & FLIP_VERTICALLY) != 0 ? -nrow : nrow;
                row += nrow;
            }

            if ((flip & FLIP_HORIZONTALLY) != 0)
            {
                for (int line = 0; line < height; line++)
                {
                    int left = offset + line * width;
                    int right = left + width - 1;

                    while (left < right)
                    {
                        int temp = raster[left];
                        raster[left] = raster[right];
                        raster[right] = temp;
                        left++;
                        right--;
                    }
                }
            }

            return ret;
        }
Exemplo n.º 15
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr42tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int rasterOffset2 = rasterOffset + width + rasterShift;
            int incr = 2 * rasterShift + width;

            bufferShift = (bufferShift * 10) / 4;
            if ((height & 3) == 0 && (width & 1) == 0)
            {
                for (; height >= 2; height -= 2)
                {
                    x = width >> 2;
                    do
                    {
                        int Cb = buffer[offset + 8];
                        int Cr = buffer[offset + 9];

                        img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset + 3], buffer[offset + 3], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 0], buffer[offset + 4], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 1], buffer[offset + 5], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 2], buffer[offset + 6], Cb, Cr);
                        img.YCbCrtoRGB(out raster[rasterOffset2 + 3], buffer[offset + 7], Cb, Cr);

                        rasterOffset += 4;
                        rasterOffset2 += 4;
                        offset += 10;
                    }
                    while (--x != 0);

                    rasterOffset += incr;
                    rasterOffset2 += incr;
                    offset += bufferShift;
                }
            }
            else
            {
                while (height > 0)
                {
                    for (x = width; x > 0; )
                    {
                        int Cb = buffer[offset + 8];
                        int Cr = buffer[offset + 9];

                        bool x_goOn = false;
                        if (x < 1 || x > 3)
                        {
                            if (height != 1)
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 3], buffer[offset + 7], Cb, Cr);

                            img.YCbCrtoRGB(out raster[rasterOffset + 3], buffer[offset + 3], Cb, Cr);
                            x_goOn = true;
                        }

                        if (x == 3 || x_goOn)
                        {
                            if (height != 1)
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 2], buffer[offset + 6], Cb, Cr);

                            img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);
                            x_goOn = true;
                        }

                        if (x == 2 || x_goOn)
                        {
                            if (height != 1)
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 1], buffer[offset + 5], Cb, Cr);

                            img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);
                            x_goOn = true;
                        }

                        if (x == 1 || x_goOn)
                        {
                            if (height != 1)
                                img.YCbCrtoRGB(out raster[rasterOffset2 + 0], buffer[offset + 4], Cb, Cr);

                            img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                        }

                        if (x < 4)
                        {
                            rasterOffset += x;
                            rasterOffset2 += x;
                            x = 0;
                        }
                        else
                        {
                            rasterOffset += 4;
                            rasterOffset2 += 4;
                            x -= 4;
                        }

                        offset += 10;
                    }

                    if (height <= 2)
                        break;

                    height -= 2;
                    rasterOffset += incr;
                    rasterOffset2 += incr;
                    offset += bufferShift;
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// 8-bit packed samples => RGBA w/ associated alpha (known to have Map == null)
        /// </summary>
        private static void putRGBAAcontig8bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            bufferShift *= samplesperpixel;

            while (height-- > 0)
            {
                int _x;
                for (_x = width; _x >= 8; _x -= 8)
                {
                    for (int rc = 0; rc < 8; rc++)
                    {
                        raster[rasterOffset] = PACK4(buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3]);
                        rasterOffset++;
                        offset += samplesperpixel;
                    }
                }

                if (_x > 0)
                {
                    if (_x <= 7 && _x > 0)
                    {
                        for (int i = _x; i > 0; i--)
                        {
                            raster[rasterOffset] = PACK4(buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3]);
                            rasterOffset++;
                            offset += samplesperpixel;
                        }
                    }
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr41tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            // XXX adjust bufferShift
            do
            {
                x = width >> 2;
                do
                {
                    int Cb = buffer[offset + 4];
                    int Cr = buffer[offset + 5];

                    img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                    img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);
                    img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);
                    img.YCbCrtoRGB(out raster[rasterOffset + 3], buffer[offset + 3], Cb, Cr);

                    rasterOffset += 4;
                    offset += 6;
                }
                while (--x != 0);

                if ((width & 3) != 0)
                {
                    int Cb = buffer[offset + 4];
                    int Cr = buffer[offset + 5];

                    int xx = width & 3;
                    if (xx == 3)
                        img.YCbCrtoRGB(out raster[rasterOffset + 2], buffer[offset + 2], Cb, Cr);

                    if (xx == 3 || xx == 2)
                        img.YCbCrtoRGB(out raster[rasterOffset + 1], buffer[offset + 1], Cb, Cr);

                    if (xx == 3 || xx == 2 || xx == 1)
                        img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);

                    rasterOffset += xx;
                    offset += 6;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
            while (--height != 0);
        }
Exemplo n.º 18
0
        /// <summary>
        /// 8-bit packed samples => RGBA w/ unassociated alpha (known to have Map == null)
        /// </summary>
        private static void putRGBUAcontig8bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            bufferShift *= samplesperpixel;
            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    int a = buffer[offset + 3];
                    int r = (buffer[offset] * a + 127) / 255;
                    int g = (buffer[offset + 1] * a + 127) / 255;
                    int b = (buffer[offset + 2] * a + 127) / 255;
                    raster[rasterOffset] = PACK4(r, g, b, a);
                    rasterOffset++;
                    offset += samplesperpixel;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
        /// </summary>
        private static void putcontig8bitYCbCr12tile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            bufferShift = (bufferShift / 2) * 4;
            int rasterOffset2 = rasterOffset + width + rasterShift;

            while (height >= 2)
            {
                x = width;
                do
                {
                    int Cb = buffer[offset + 2];
                    int Cr = buffer[offset + 3];
                    img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                    img.YCbCrtoRGB(out raster[rasterOffset2 + 0], buffer[offset + 1], Cb, Cr);
                    rasterOffset++;
                    rasterOffset2++;
                    offset += 4;
                } while (--x != 0);

                rasterOffset += rasterShift * 2 + width;
                rasterOffset2 += rasterShift * 2 + width;
                offset += bufferShift;
                height -= 2;
            }

            if (height == 1)
            {
                x = width;
                do
                {
                    int Cb = buffer[offset + 2];
                    int Cr = buffer[offset + 3];
                    img.YCbCrtoRGB(out raster[rasterOffset + 0], buffer[offset + 0], Cb, Cr);
                    rasterOffset++;
                    offset += 4;
                } while (--x != 0);
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// 16-bit packed samples => RGBA w/ unassociated alpha (known to have Map == null)
        /// </summary>
        private static void putRGBUAcontig16bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            bufferShift *= samplesperpixel;

            short[] wp = Tiff.ByteArrayToShorts(buffer, offset, buffer.Length);
            int wpPos = 0;

            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    int a = W2B(wp[wpPos + 3]);
                    int r = (W2B(wp[wpPos]) * a + 127) / 255;
                    int g = (W2B(wp[wpPos + 1]) * a + 127) / 255;
                    int b = (W2B(wp[wpPos + 2]) * a + 127) / 255;
                    raster[rasterOffset] = PACK4(r, g, b, a);
                    rasterOffset++;
                    wpPos += samplesperpixel;
                }

                rasterOffset += rasterShift;
                wpPos += bufferShift;
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// 8-bit unpacked samples => RGBA w/ unassociated alpha
        /// </summary>
        private static void putRGBUAseparate8bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height,
            byte[] buffer, int offset1, int offset2, int offset3, int offset4, int bufferShift)
        {
            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    int av = buffer[offset4];
                    int rv = (buffer[offset1] * av + 127) / 255;
                    int gv = (buffer[offset2] * av + 127) / 255;
                    int bv = (buffer[offset3] * av + 127) / 255;
                    raster[rasterOffset] = PACK4(rv, gv, bv, av);
                    rasterOffset++;
                    offset1++;
                    offset2++;
                    offset3++;
                    offset4++;
                }

                offset1 += bufferShift;
                offset2 += bufferShift;
                offset3 += bufferShift;
                offset4 += bufferShift;

                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 22
0
        /// <summary>
        /// 8-bit packed CMYK samples w/o Map => RGB.
        /// NB: The conversion of CMYK->RGB is *very* crude.
        /// </summary>
        private static void putRGBcontig8bitCMYKtile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            bufferShift *= samplesperpixel;

            while (height-- > 0)
            {
                int _x;
                for (_x = width; _x >= 8; _x -= 8)
                {
                    for (int rc = 0; rc < 8; rc++)
                    {
                        short k = (short)(255 - buffer[offset + 3]);
                        short r = (short)((k * (255 - buffer[offset])) / 255);
                        short g = (short)((k * (255 - buffer[offset + 1])) / 255);
                        short b = (short)((k * (255 - buffer[offset + 2])) / 255);
                        raster[rasterOffset] = PACK(r, g, b);
                        rasterOffset++;
                        offset += samplesperpixel;
                    }
                }

                if (_x > 0)
                {
                    if (_x <= 7 && _x > 0)
                    {
                        for (int i = _x; i > 0; i--)
                        {
                            short k = (short)(255 - buffer[offset + 3]);
                            short r = (short)((k * (255 - buffer[offset])) / 255);
                            short g = (short)((k * (255 - buffer[offset + 1])) / 255);
                            short b = (short)((k * (255 - buffer[offset + 2])) / 255);
                            raster[rasterOffset] = PACK(r, g, b);
                            rasterOffset++;
                            offset += samplesperpixel;
                        }
                    }
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 23
0
        /// <summary>
        /// 16-bit unpacked samples => RGBA w/ unassociated alpha
        /// </summary>
        private static void putRGBUAseparate16bittile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height,
            byte[] buffer, int offset1, int offset2, int offset3, int offset4, int bufferShift)
        {
            short[] wrgba = Tiff.ByteArrayToShorts(buffer, 0, buffer.Length);

            offset1 /= sizeof(short);
            offset2 /= sizeof(short);
            offset3 /= sizeof(short);
            offset4 /= sizeof(short);

            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    int a = W2B(wrgba[offset4]);
                    int r = (W2B(wrgba[offset1]) * a + 127) / 255;
                    int g = (W2B(wrgba[offset2]) * a + 127) / 255;
                    int b = (W2B(wrgba[offset3]) * a + 127) / 255;
                    raster[rasterOffset] = PACK4(r, g, b, a);
                    rasterOffset++;
                    offset1++;
                    offset2++;
                    offset3++;
                    offset4++;
                }

                offset1 += bufferShift;
                offset2 += bufferShift;
                offset3 += bufferShift;
                offset4 += bufferShift;

                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 24
0
        /// <summary>
        /// 8-bit packed CIE L*a*b 1976 samples => RGB
        /// </summary>
        private static void putcontig8bitCIELab(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            bufferShift *= 3;

            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    float X, Y, Z;
                    img.cielab.CIELabToXYZ(buffer[offset], (sbyte)buffer[offset + 1], (sbyte)buffer[offset + 2], out X, out Y, out Z);

                    int r, g, b;
                    img.cielab.XYZToRGB(X, Y, Z, out r, out g, out b);

                    raster[rasterOffset] = PACK(r, g, b);
                    rasterOffset++;
                    offset += 3;
                }

                rasterOffset += rasterShift;
                offset += bufferShift;
            }
        }
Exemplo n.º 25
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        // Untested methods
        //
        // This methods are untested (and, probably, should be deleted).
        //
        // pickContigCase implicitly *excludes* putRGBcontig8bitCMYKMaptile from possible "put"
        //                methods when it requires images to have Photometric.Separated *and* 8-bit
        //                samples *and* a Map to use putRGBcontig8bitCMYKMaptile. The problem is:
        //                no Map is ever built for Photometric.Separated *and* 8-bit samples.

        /// <summary>
        /// 8-bit packed CMYK samples w/Map => RGB
        /// NB: The conversion of CMYK->RGB is *very* crude.
        /// </summary>
        private static void putRGBcontig8bitCMYKMaptile(
            TiffRgbaImage img, int[] raster, int rasterOffset, int rasterShift,
            int x, int y, int width, int height, byte[] buffer, int offset, int bufferShift)
        {
            int samplesperpixel = img.samplesperpixel;
            byte[] Map = img.Map;
            bufferShift *= samplesperpixel;

            while (height-- > 0)
            {
                for (x = width; x-- > 0; )
                {
                    short k = (short)(255 - buffer[offset + 3]);
                    short r = (short)((k * (255 - buffer[offset])) / 255);
                    short g = (short)((k * (255 - buffer[offset + 1])) / 255);
                    short b = (short)((k * (255 - buffer[offset + 2])) / 255);
                    raster[rasterOffset] = PACK(Map[r], Map[g], Map[b]);
                    rasterOffset++;
                    offset += samplesperpixel;
                }

                offset += bufferShift;
                rasterOffset += rasterShift;
            }
        }
Exemplo n.º 26
0
        /// <summary>
        /// Creates new instance of the <see cref="TiffRgbaImage"/> class.
        /// </summary>
        /// <param name="tif">
        /// The instance of the <see cref="BitMiracle.LibTiff.Classic"/> class used to retrieve
        /// image data.
        /// </param>
        /// <param name="stopOnError">
        /// if set to <c>true</c> then an error will terminate the conversion; otherwise "get"
        /// methods will continue processing data until all the possible data in the image have
        /// been requested.
        /// </param>
        /// <param name="errorMsg">The error message (if any) gets placed here.</param>
        /// <returns>
        /// New instance of the <see cref="TiffRgbaImage"/> class if the image specified
        /// by <paramref name="tif"/> can be converted to RGBA format; otherwise, <c>null</c> is
        /// returned and <paramref name="errorMsg"/> contains the reason why it is being
        /// rejected.
        /// </returns>
        public static TiffRgbaImage Create(Tiff tif, bool stopOnError, out string errorMsg)
        {
            errorMsg = null;

            // Initialize to normal values
            TiffRgbaImage img = new TiffRgbaImage();
            img.row_offset = 0;
            img.col_offset = 0;
            img.redcmap = null;
            img.greencmap = null;
            img.bluecmap = null;
            img.req_orientation = Orientation.BottomLeft; // It is the default
            img.tif = tif;
            img.stoponerr = stopOnError;

            FieldValue[] result = tif.GetFieldDefaulted(TiffTag.BitsPerSample);
            img.bitspersample = result[0].ToShort();
            switch (img.bitspersample)
            {
                case 1:
                case 2:
                case 4:
                case 8:
                case 16:
                    break;

                default:
                    errorMsg = string.Format(CultureInfo.InvariantCulture,
                        "Sorry, can not handle images with {0}-bit samples", img.bitspersample);
                    return null;
            }

            img.alpha = 0;
            result = tif.GetFieldDefaulted(TiffTag.SamplesPerPixel);
            img.samplesperpixel = result[0].ToShort();

            result = tif.GetFieldDefaulted(TiffTag.ExtraSamples);
            short extrasamples = result[0].ToShort();
            byte[] sampleinfo = result[1].ToByteArray();

            if (extrasamples >= 1)
            {
                switch ((ExtraSample)sampleinfo[0])
                {
                    case ExtraSample.UnSpecified:
                        if (img.samplesperpixel > 3)
                        {
                            // Workaround for some images without correct info about alpha channel
                            img.alpha = ExtraSample.AssociatedAlpha;
                        }
                        break;

                    case ExtraSample.AssociatedAlpha:
                    // data is pre-multiplied
                    case ExtraSample.UnAssociatedAlpha:
                        // data is not pre-multiplied
                        img.alpha = (ExtraSample)sampleinfo[0];
                        break;
                }
            }

            if (Tiff.DEFAULT_EXTRASAMPLE_AS_ALPHA)
            {
                result = tif.GetField(TiffTag.Photometric);
                if (result == null)
                    img.photometric = Photometric.MinIsWhite;

                if (extrasamples == 0 && img.samplesperpixel == 4 && img.photometric == Photometric.RGB)
                {
                    img.alpha = ExtraSample.AssociatedAlpha;
                    extrasamples = 1;
                }
            }

            int colorchannels = img.samplesperpixel - extrasamples;

            result = tif.GetFieldDefaulted(TiffTag.Compression);
            Compression compress = (Compression)result[0].ToInt();

            result = tif.GetFieldDefaulted(TiffTag.PlanarConfig);
            PlanarConfig planarconfig = (PlanarConfig)result[0].ToShort();

            result = tif.GetField(TiffTag.Photometric);
            if (result == null)
            {
                switch (colorchannels)
                {
                    case 1:
                        if (img.isCCITTCompression())
                            img.photometric = Photometric.MinIsWhite;
                        else
                            img.photometric = Photometric.MinIsBlack;
                        break;

                    case 3:
                        img.photometric = Photometric.RGB;
                        break;

                    default:
                        errorMsg = string.Format(CultureInfo.InvariantCulture, "Missing needed {0} tag", photoTag);
                        return null;
                }
            }
            else
                img.photometric = (Photometric)result[0].ToInt();

            switch (img.photometric)
            {
                case Photometric.Palette:
                    result = tif.GetField(TiffTag.Colormap);
                    if (result == null)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture, "Missing required \"Colormap\" tag");
                        return null;
                    }

                    short[] red_orig = result[0].ToShortArray();
                    short[] green_orig = result[1].ToShortArray();
                    short[] blue_orig = result[2].ToShortArray();

                    // copy the colormaps so we can modify them
                    int n_color = (1 << img.bitspersample);
                    img.redcmap = new short[n_color];
                    img.greencmap = new short[n_color];
                    img.bluecmap = new short[n_color];

                    Buffer.BlockCopy(red_orig, 0, img.redcmap, 0, n_color * sizeof(short));
                    Buffer.BlockCopy(green_orig, 0, img.greencmap, 0, n_color * sizeof(short));
                    Buffer.BlockCopy(blue_orig, 0, img.bluecmap, 0, n_color * sizeof(short));

                    if (planarconfig == PlanarConfig.Contig &&
                        img.samplesperpixel != 1 && img.bitspersample < 8)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle contiguous data with {0}={1}, and {2}={3} and Bits/Sample={4}",
                            photoTag, img.photometric, "Samples/pixel", img.samplesperpixel, img.bitspersample);
                        return null;
                    }
                    break;

                case Photometric.MinIsWhite:
                case Photometric.MinIsBlack:
                    if (planarconfig == PlanarConfig.Contig &&
                        img.samplesperpixel != 1 && img.bitspersample < 8)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle contiguous data with {0}={1}, and {2}={3} and Bits/Sample={4}",
                            photoTag, img.photometric, "Samples/pixel", img.samplesperpixel, img.bitspersample);
                        return null;
                    }
                    break;

                case Photometric.YCBCR:
                    // It would probably be nice to have a reality check here.
                    if (planarconfig == PlanarConfig.Contig)
                    {
                        // can rely on LibJpeg.Net to convert to RGB
                        // XXX should restore current state on exit
                        switch (compress)
                        {
                            case Compression.JPEG:
                                // TODO: when complete tests verify complete desubsampling and
                                // YCbCr handling, remove use of JPEGCOLORMODE in favor of native
                                // handling
                                tif.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RGB);
                                img.photometric = Photometric.RGB;
                                break;

                            default:
                                // do nothing
                                break;
                        }
                    }

                    // TODO: if at all meaningful and useful, make more complete support check
                    // here, or better still, refactor to let supporting code decide whether there
                    // is support and what meaningfull error to return
                    break;

                case Photometric.RGB:
                    if (colorchannels < 3)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle RGB image with {0}={1}", "Color channels", colorchannels);
                        return null;
                    }
                    break;

                case Photometric.Separated:
                    result = tif.GetFieldDefaulted(TiffTag.InkSet);
                    InkSet inkset = (InkSet)result[0].ToByte();

                    if (inkset != InkSet.CMYK)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle separated image with {0}={1}", "InkSet", inkset);
                        return null;
                    }

                    if (img.samplesperpixel < 4)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle separated image with {0}={1}", "Samples/pixel", img.samplesperpixel);
                        return null;
                    }
                    break;

                case Photometric.LogL:
                    if (compress != Compression.SGILOG)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, LogL data must have {0}={1}", "Compression", Compression.SGILOG);
                        return null;
                    }

                    tif.SetField(TiffTag.SGILOGDATAFMT, 3); // 8-bit RGB monitor values. 
                    img.photometric = Photometric.MinIsBlack; // little white lie
                    img.bitspersample = 8;
                    break;

                case Photometric.LogLUV:
                    if (compress != Compression.SGILOG && compress != Compression.SGILOG24)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, LogLuv data must have {0}={1} or {2}", "Compression", Compression.SGILOG, Compression.SGILOG24);
                        return null;
                    }

                    if (planarconfig != PlanarConfig.Contig)
                    {
                        errorMsg = string.Format(CultureInfo.InvariantCulture,
                            "Sorry, can not handle LogLuv images with {0}={1}", "Planarconfiguration", planarconfig);
                        return null;
                    }

                    tif.SetField(TiffTag.SGILOGDATAFMT, 3); // 8-bit RGB monitor values. 
                    img.photometric = Photometric.RGB; // little white lie
                    img.bitspersample = 8;
                    break;

                case Photometric.CIELAB:
                    break;

                default:
                    errorMsg = string.Format(CultureInfo.InvariantCulture,
                        "Sorry, can not handle image with {0}={1}", photoTag, img.photometric);
                    return null;
            }

            img.Map = null;
            img.BWmap = null;
            img.PALmap = null;
            img.ycbcr = null;
            img.cielab = null;

            result = tif.GetField(TiffTag.ImageWidth);
            img.width = result[0].ToInt();

            result = tif.GetField(TiffTag.ImageLength);
            img.height = result[0].ToInt();

            result = tif.GetFieldDefaulted(TiffTag.Orientation);
            img.orientation = (Orientation)result[0].ToByte();

            img.isContig = !(planarconfig == PlanarConfig.Separate && colorchannels > 1);
            if (img.isContig)
            {
                if (!img.pickContigCase())
                {
                    errorMsg = "Sorry, can not handle image";
                    return null;
                }
            }
            else
            {
                if (!img.pickSeparateCase())
                {
                    errorMsg = "Sorry, can not handle image";
                    return null;
                }
            }

            return img;
        }