예제 #1
0
 static bool TIFFWriteByteArray(TIFF tif, TIFFDirEntry dir, sbyte[] cp)
 {
     byte[] buf=new byte[dir.tdir_count];
     for(int i=0; i<dir.tdir_count; i++) buf[i]=(byte)cp[i];
     return TIFFWriteByteArray(tif, dir, buf);
 }
예제 #2
0
        // Fetch and set the SubjectDistance EXIF tag.
        static bool TIFFFetchSubjectDistance(TIFF tif, TIFFDirEntry dir)
        {
            if(dir.tdir_count!=1||dir.tdir_type!=(ushort)TIFFDataType.TIFF_RATIONAL)
            {
                TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "incorrect count or type for SubjectDistance, tag ignored");
                return false;
            }

            bool ok=false;
            byte[] buf=new byte[8];
            if(TIFFFetchData(tif, dir, buf)!=0)
            {
                uint l0=BitConverter.ToUInt32(buf, 0);
                uint l1=BitConverter.ToUInt32(buf, 4);
                double v;
                if(cvtRational(tif, dir, l0, l1, out v))
                {
                    // XXX: Numerator 0xFFFFFFFF means that we have infinite
                    // distance. Indicate that with a negative floating point
                    // SubjectDistance value.
                    ok=TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (l0!=0xFFFFFFFF)?v:-v);
                }
            }

            return ok;
        }
예제 #3
0
        // Convert numerator+denominator to double.
        static bool cvtRational(TIFF tif, TIFFDirEntry dir, uint num, uint denom, out double rv)
        {
            if(num==0&&denom==0)
            {
                rv=0;
                return true;
            }

            if(denom==0)
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Rational with zero denominator (num = {1})", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name, num);
                rv=double.NaN;
                return false;
            }

            if((TIFFDataType)dir.tdir_type==TIFFDataType.TIFF_RATIONAL) rv=((double)num/(double)denom);
            else rv=((double)(int)num/(double)(int)denom);

            return true;
        }
예제 #4
0
        // Fetch an array of SSHORT values.
        static bool TIFFFetchShortArray(TIFF tif, TIFFDirEntry dir, short[] v)
        {
            if(dir.tdir_count<=2)
            {
                if(tif.tif_header.tiff_magic==TIFF_BIGENDIAN)
                {
                    switch(dir.tdir_count)
                    {
                        case 2: v[1]=(short)(dir.tdir_offset&0xffff); goto case 1;
                        case 1: v[0]=(short)(dir.tdir_offset>>16); break;
                    }
                }
                else
                {
                    switch(dir.tdir_count)
                    {
                        case 2: v[1]=(short)(dir.tdir_offset>>16); goto case 1;
                        case 1: v[0]=(short)(dir.tdir_offset&0xffff); break;
                    }
                }
                return true;
            }

            byte[] buf=new byte[dir.tdir_count*2];
            if(TIFFFetchData(tif, dir, buf)==0) return false;
            for(int i=0; i<dir.tdir_count; i++) v[i]=BitConverter.ToInt16(buf, i*2);
            return true;
        }
예제 #5
0
        // Fetch an ASCII item from the file.
        static int TIFFFetchString(TIFF tif, TIFFDirEntry dir, out string cp)
        {
            if(dir.tdir_count<=4)
            {
                uint l=dir.tdir_offset;
                if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)!=0) TIFFSwab(ref l); // swab 'back' see in TIFFReadDirectory & TIFFReadCustomDirectory

                cp=System.Text.Encoding.ASCII.GetString(BitConverter.GetBytes(l));
                return 1;
            }

            cp=null;

            byte[] buf=new byte[dir.tdir_count];
            int ret=TIFFFetchData(tif, dir, buf);
            if(ret==0) return 0;

            cp=System.Text.Encoding.ASCII.GetString(buf);
            return ret;
        }
예제 #6
0
        // Fetch samples/pixel short values for
        // the specified tag and verify that
        // all values are the same.
        static bool TIFFFetchPerSampleShorts(TIFF tif, TIFFDirEntry dir, out ushort pl)
        {
            ushort samples=tif.tif_dir.td_samplesperpixel;

            pl=0;
            if(!CheckDirCount(tif, dir, samples)) return false;

            ushort[] v=null;
            try
            {
                v=new ushort[dir.tdir_count];
            }
            catch
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to fetch per-sample values");
                return false;
            }

            if(TIFFFetchShortArray(tif, dir, v))
            {
                uint check_count=dir.tdir_count;
                if(samples<check_count) check_count=samples;

                for(uint i=1; i<check_count; i++)
                {
                    if(v[i]!=v[0])
                    {
                        TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Cannot handle different per-sample values for field \"{0}\"", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
                        return false;
                    }
                }
                pl=v[0];
            }

            return true;
        }
예제 #7
0
        // Fetch an array of RATIONAL or SRATIONAL values.
        static bool TIFFFetchRationalArray(TIFF tif, TIFFDirEntry dir, double[] v)
        {
            byte[] buf=null;
            try
            {
                buf=new byte[dir.tdir_count*8];
            }
            catch
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to fetch array of rationals");
                return false;
            }

            for(int i=0; i<dir.tdir_count; i++)
            {
                if(!cvtRational(tif, dir, BitConverter.ToUInt32(buf, i*8), BitConverter.ToUInt32(buf, i*8+4), out v[i])) return false;
            }
            return true;
        }
예제 #8
0
        // Process tags that are not special cased.
        static bool TIFFWriteNormalTag(TIFF tif, TIFFDirEntry dir, TIFFFieldInfo fip)
        {
            uint wc=(uint)fip.field_writecount;

            dir.tdir_tag=(ushort)fip.field_tag;
            dir.tdir_type=(ushort)fip.field_type;
            dir.tdir_count=wc;

            switch(fip.field_type)
            {
                case TIFFDataType.TIFF_SHORT:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            ushort[] wp=ap[1] as ushort[];
                            if(wp==null) return false;

                            if(!TIFFWriteShortArray(tif, dir, wp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                ushort sv=__GetAsUshort(ap, 0);
                                //was dir.tdir_offset=TIFFInsertData(tif, dir.tdir_type, sv);
                                dir.tdir_offset=((uint)(tif.tif_header.tiff_magic==TIFF_BIGENDIAN?(sv&tif_typemask[dir.tdir_type])<<tif_typeshift[dir.tdir_type]:sv&tif_typemask[dir.tdir_type]));
                            }
                            else
                            {
                                ushort[] wp=ap[0] as ushort[];
                                if(wp==null) return false;

                                if(!TIFFWriteShortArray(tif, dir, wp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_SSHORT:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            short[] wp=ap[1] as short[];
                            if(wp==null) return false;

                            if(!TIFFWriteShortArray(tif, dir, wp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                short sv=__GetAsShort(ap, 0);
                                //was dir.tdir_offset=TIFFInsertData(tif, dir.tdir_type, sv);
                                dir.tdir_offset=((uint)(tif.tif_header.tiff_magic==TIFF_BIGENDIAN?(sv&tif_typemask[dir.tdir_type])<<tif_typeshift[dir.tdir_type]:sv&tif_typemask[dir.tdir_type]));
                            }
                            else
                            {
                                short[] wp=ap[0] as short[];
                                if(wp==null) return false;

                                if(!TIFFWriteShortArray(tif, dir, wp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_SLONG:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            int[] lp=ap[1] as int[];
                            if(lp==null) return false;

                            if(!TIFFWriteLongArray(tif, dir, lp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                // XXX handle LONG=>SHORT conversion
                                dir.tdir_offset=__GetAsUint(ap, 0);
                            }
                            else
                            {
                                int[] lp=ap[0] as int[];
                                if(lp==null) return false;

                                if(!TIFFWriteLongArray(tif, dir, lp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_LONG:
                case TIFFDataType.TIFF_IFD:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            uint[] lp=ap[1] as uint[];
                            if(lp==null) return false;

                            if(!TIFFWriteLongArray(tif, dir, lp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                // XXX handle LONG=>SHORT conversion
                                dir.tdir_offset=__GetAsUint(ap, 0);
                            }
                            else
                            {
                                uint[] lp=ap[0] as uint[];
                                if(lp==null) return false;

                                if(!TIFFWriteLongArray(tif, dir, lp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_RATIONAL:
                case TIFFDataType.TIFF_SRATIONAL:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            double[] fp=ap[1] as double[];
                            if(fp==null) return false;

                            if(!TIFFWriteRationalArray(tif, dir, fp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                double fv=__GetAsDouble(ap, 0);
                                if(!TIFFWriteRational(tif, fip.field_type, fip.field_tag, dir, fv)) return false;
                            }
                            else
                            {
                                double[] fp=ap[0] as double[];
                                if(fp==null) return false;

                                if(!TIFFWriteRationalArray(tif, dir, fp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_FLOAT:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            float[] fp=ap[1] as float[];
                            if(fp==null) return false;

                            if(!TIFFWriteFloatArray(tif, dir, fp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                float[] fv=new float[1];
                                fv[0]=__GetAsFloat(ap, 0);
                                if(!TIFFWriteFloatArray(tif, dir, fv)) return false;
                            }
                            else
                            {
                                float[] fp=ap[0] as float[];
                                if(fp==null) return false;

                                if(!TIFFWriteFloatArray(tif, dir, fp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_DOUBLE:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            double[] dp=ap[1] as double[];
                            if(dp==null) return false;

                            if(!TIFFWriteDoubleArray(tif, dir, dp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                double[] dv=new double[1];
                                dv[0]=__GetAsDouble(ap, 0);

                                if(!TIFFWriteDoubleArray(tif, dir, dv)) return false;
                            }
                            else
                            {
                                double[] dp=ap[0] as double[];
                                if(dp==null) return false;

                                if(!TIFFWriteDoubleArray(tif, dir, dp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_ASCII:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        string cp;
                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            wc=__GetAsUint(ap, 0);
                            cp=ap[1] as string;
                            if(cp==null) return false;
                        }
                        else
                        {
                            cp=ap[0] as string;
                            if(cp==null) return false;
                        }

                        cp=cp.TrimEnd('\0');
                        cp+='\0';
                        dir.tdir_count=(uint)cp.Length;
                        if(!TIFFWriteByteArray(tif, dir, Encoding.ASCII.GetBytes(cp))) return false;
                    }
                    break;
                case TIFFDataType.TIFF_BYTE:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            byte[] cp=ap[1] as byte[];
                            if(cp==null) return false;

                            if(!TIFFWriteByteArray(tif, dir, cp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                byte[] cv=new byte[1];
                                cv[0]=__GetAsByte(ap, 0);

                                if(!TIFFWriteByteArray(tif, dir, cv)) return false;
                            }
                            else
                            {
                                byte[] cp=ap[0] as byte[];
                                if(cp==null) return false;

                                if(!TIFFWriteByteArray(tif, dir, cp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_SBYTE:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        if(fip.field_passcount)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            sbyte[] cp=ap[1] as sbyte[];
                            if(cp==null) return false;

                            if(!TIFFWriteByteArray(tif, dir, cp)) return false;
                        }
                        else
                        {
                            if(wc==1)
                            {
                                sbyte[] cv=new sbyte[1];
                                cv[0]=__GetAsSbyte(ap, 0);

                                if(!TIFFWriteByteArray(tif, dir, cv)) return false;
                            }
                            else
                            {
                                sbyte[] cp=ap[0] as sbyte[];
                                if(cp==null) return false;

                                if(!TIFFWriteByteArray(tif, dir, cp)) return false;
                            }
                        }
                    }
                    break;
                case TIFFDataType.TIFF_UNDEFINED:
                    {
                        object[] ap=new object[2];
                        TIFFGetField(tif, fip.field_tag, ap);

                        byte[] cp;
                        if((int)wc==TIFF_VARIABLE)
                        {
                            // Assume TIFF_VARIABLE
                            dir.tdir_count=wc=__GetAsUint(ap, 0);
                            cp=ap[1] as byte[];
                            if(cp==null) return false;
                        }
                        else
                        {
                            cp=ap[0] as byte[];
                            if(cp==null) return false;
                        }

                        if(!TIFFWriteByteArray(tif, dir, cp)) return false;
                    }
                    break;
                case TIFFDataType.TIFF_NOTYPE:
                    break;
            }
            return true;
        }
예제 #9
0
        // Fetch an array of BYTE values.
        static bool TIFFFetchByteArray(TIFF tif, TIFFDirEntry dir, byte[] v)
        {
            if(dir.tdir_count<=4)
            {
                // Extract data from offset field.
                if(tif.tif_header.tiff_magic==TIFF_BIGENDIAN)
                {
                    switch(dir.tdir_count)
                    {
                        case 4: v[3]=(byte)(dir.tdir_offset&0xff); goto case 3;
                        case 3: v[2]=(byte)((dir.tdir_offset>>8)&0xff); goto case 2;
                        case 2: v[1]=(byte)((dir.tdir_offset>>16)&0xff); goto case 1;
                        case 1: v[0]=(byte)(dir.tdir_offset>>24); break;
                    }
                }
                else
                {
                    switch(dir.tdir_count)
                    {
                        case 4: v[3]=(byte)(dir.tdir_offset>>24); goto case 3;
                        case 3: v[2]=(byte)((dir.tdir_offset>>16)&0xff); goto case 2;
                        case 2: v[1]=(byte)((dir.tdir_offset>>8)&0xff); goto case 1;
                        case 1: v[0]=(byte)(dir.tdir_offset&0xff); break;
                    }
                }
                return true;
            }

            return TIFFFetchData(tif, dir, v)!=0;
        }
예제 #10
0
        static bool TIFFWriteInkNames(TIFF tif, TIFFDirEntry dir)
        {
            TIFFDirectory td=tif.tif_dir;

            dir.tdir_tag=(ushort)TIFFTAG.INKNAMES;
            dir.tdir_type=(ushort)TIFFDataType.TIFF_ASCII;

            string cp=td.td_inknames;
            cp=cp.TrimEnd('\0');
            cp+='\0';
            dir.tdir_count=(uint)cp.Length;

            return TIFFWriteByteArray(tif, dir, Encoding.ASCII.GetBytes(cp));
        }
예제 #11
0
        // Setup a directory entry of an array of
        // SLONG and write the associated indirect values.
        static bool TIFFWriteLongArray(TIFF tif, TIFFDirEntry dir, int[] v)
        {
            if(dir.tdir_count==1)
            {
                dir.tdir_offset=(uint)v[0];
                return true;
            }

            byte[] buf=new byte[dir.tdir_count*4];
            for(int i=0; i<dir.tdir_count; i++) BitConverter.GetBytes(v[i]).CopyTo(buf, i*4);
            return TIFFWriteData(tif, dir, buf);
        }
예제 #12
0
        static bool TIFFWriteFloatArray(TIFF tif, TIFFDirEntry dir, float[] v)
        {
            byte[] buf=new byte[dir.tdir_count*4];
            for(int i=0; i<dir.tdir_count; i++) BitConverter.GetBytes(v[i]).CopyTo(buf, i*4);

            if(dir.tdir_count==1)
            {
                dir.tdir_offset=((uint)buf[3]<<24)+((uint)buf[2]<<16)+((uint)buf[1]<<8)+(uint)buf[0];
                return true;
            }

            return TIFFWriteData(tif, dir, buf);
        }
예제 #13
0
 static bool TIFFWriteDoubleArray(TIFF tif, TIFFDirEntry dir, double[] v)
 {
     byte[] buf=new byte[dir.tdir_count*8];
     for(int i=0; i<dir.tdir_count; i++) BitConverter.GetBytes(v[i]).CopyTo(buf, i*8);
     return TIFFWriteData(tif, dir, buf);
 }
예제 #14
0
        // Write a contiguous directory item.
        static bool TIFFWriteData(TIFF tif, TIFFDirEntry dir, byte[] cp)
        {
            if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)!=0)
            {
                switch((TIFFDataType)dir.tdir_type)
                {
                    case TIFFDataType.TIFF_SHORT:
                    case TIFFDataType.TIFF_SSHORT:
                        TIFFSwabArrayOfShort(cp, dir.tdir_count);
                        break;
                    case TIFFDataType.TIFF_LONG:
                    case TIFFDataType.TIFF_SLONG:
                    case TIFFDataType.TIFF_FLOAT:
                        TIFFSwabArrayOfLong(cp, dir.tdir_count);
                        break;
                    case TIFFDataType.TIFF_RATIONAL:
                    case TIFFDataType.TIFF_SRATIONAL:
                        TIFFSwabArrayOfLong(cp, 2*dir.tdir_count);
                        break;
                    case TIFFDataType.TIFF_DOUBLE:
                        TIFFSwabArrayOfDouble(cp, dir.tdir_count);
                        break;
                }
            }

            dir.tdir_offset=tif.tif_dataoff;
            int cc=(int)dir.tdir_count*TIFFDataWidth((TIFFDataType)dir.tdir_type);

            if(SeekOK(tif, dir.tdir_offset)&&WriteOK(tif, cp, cc))
            {
                tif.tif_dataoff+=(uint)((cc+1)&~1);
                return true;
            }

            TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Error writing data for field \"{0}\"", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
            return false;
        }
예제 #15
0
        // Fetch an array of SLONG values.
        static bool TIFFFetchLongArray(TIFF tif, TIFFDirEntry dir, int[] v)
        {
            if(dir.tdir_count==1)
            {
                v[0]=(int)dir.tdir_offset;
                return true;
            }

            byte[] buf=new byte[dir.tdir_count*4];
            if(TIFFFetchData(tif, dir, buf)==0) return false;
            for(int i=0; i<dir.tdir_count; i++) v[i]=BitConverter.ToInt32(buf, i*4);
            return true;
        }
예제 #16
0
        // Fetch an array of SBYTE values.
        static bool TIFFFetchByteArray(TIFF tif, TIFFDirEntry dir, sbyte[] v)
        {
            if(dir.tdir_count<=4)
            {
                // Extract data from offset field.
                if(tif.tif_header.tiff_magic==TIFF_BIGENDIAN)
                {
                    switch(dir.tdir_count)
                    {
                        case 4: v[3]=(sbyte)(dir.tdir_offset&0xff); goto case 3;
                        case 3: v[2]=(sbyte)((dir.tdir_offset>>8)&0xff); goto case 2;
                        case 2: v[1]=(sbyte)((dir.tdir_offset>>16)&0xff); goto case 1;
                        case 1: v[0]=(sbyte)(dir.tdir_offset>>24); break;
                    }
                }
                else
                {
                    switch(dir.tdir_count)
                    {
                        case 4: v[3]=(sbyte)(dir.tdir_offset>>24); goto case 3;
                        case 3: v[2]=(sbyte)((dir.tdir_offset>>16)&0xff); goto case 2;
                        case 2: v[1]=(sbyte)((dir.tdir_offset>>8)&0xff); goto case 1;
                        case 1: v[0]=(sbyte)(dir.tdir_offset&0xff); break;
                    }
                }
                return true;
            }

            byte[] buf=new byte[dir.tdir_count];
            if(TIFFFetchData(tif, dir, buf)==0) return false;
            for(int i=0; i<dir.tdir_count; i++) v[i]=(sbyte)buf[i];
            return true;
        }
예제 #17
0
        // Fetch a tag that is not handled by special case code.
        static bool TIFFFetchNormalTag(TIFF tif, TIFFDirEntry dp)
        {
            bool ok=false;
            TIFFFieldInfo fip=TIFFFieldWithTag(tif, (TIFFTAG)dp.tdir_tag);

            if(dp.tdir_count>1)
            {
                // array of values
                object cp=null;

                try
                {
                    switch((TIFFDataType)dp.tdir_type)
                    {
                        case TIFFDataType.TIFF_UNDEFINED:
                        case TIFFDataType.TIFF_BYTE:
                            cp=new byte[dp.tdir_count];
                            ok=TIFFFetchByteArray(tif, dp, (byte[])cp);
                            break;
                        case TIFFDataType.TIFF_SBYTE:
                            cp=new sbyte[dp.tdir_count];
                            ok=TIFFFetchByteArray(tif, dp, (sbyte[])cp);
                            break;
                        case TIFFDataType.TIFF_SHORT:
                            cp=new ushort[dp.tdir_count];
                            ok=TIFFFetchShortArray(tif, dp, (ushort[])cp);
                            break;
                        case TIFFDataType.TIFF_SSHORT:
                            cp=new short[dp.tdir_count];
                            ok=TIFFFetchShortArray(tif, dp, (short[])cp);
                            break;
                        case TIFFDataType.TIFF_LONG:
                            cp=new uint[dp.tdir_count];
                            ok=TIFFFetchLongArray(tif, dp, (uint[])cp);
                            break;
                        case TIFFDataType.TIFF_SLONG:
                            cp=new int[dp.tdir_count];
                            ok=TIFFFetchLongArray(tif, dp, (int[])cp);
                            break;
                        case TIFFDataType.TIFF_RATIONAL:
                        case TIFFDataType.TIFF_SRATIONAL:
                            cp=new double[dp.tdir_count];
                            ok=TIFFFetchRationalArray(tif, dp, (double[])cp);
                            break;
                        case TIFFDataType.TIFF_FLOAT:
                            cp=new float[dp.tdir_count];
                            ok=TIFFFetchFloatArray(tif, dp, (float[])cp);
                            break;
                        case TIFFDataType.TIFF_DOUBLE:
                            cp=new double[dp.tdir_count];
                            ok=TIFFFetchDoubleArray(tif, dp, (double[])cp);
                            break;
                        case TIFFDataType.TIFF_ASCII:
                            // Some vendors write strings w/o the trailing
                            // NIL byte, so always append one just in case.
                            string str;
                            ok=TIFFFetchString(tif, dp, out str)!=0;
                            if(ok)
                            {
                                str=str.TrimEnd('\0');
                                str+='\0'; // XXX paranoid
                                cp=str;
                            }
                            break;
                    }
                }
                catch
                {
                    TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to fetch tag value");
                }

                if(ok)
                {
                    if(fip.field_passcount) ok=TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, dp.tdir_count, cp);
                    else
                    {
                        //if(cp is Array)
                        //{
                        //    Array arr=cp as Array;
                        //    object[] ap=new object[arr.Length];
                        //    int i=0;
                        //    foreach(object a in arr) ap[i++]=a;

                        //    ok=TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, ap);
                        //}
                        //else
                        ok=TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, cp);
                    }
                }
            }
            else if(CheckDirCount(tif, dp, 1))
            { // singleton value
                switch((TIFFDataType)dp.tdir_type)
                {
                    case TIFFDataType.TIFF_UNDEFINED:
                    case TIFFDataType.TIFF_BYTE:
                    case TIFFDataType.TIFF_SBYTE:
                    case TIFFDataType.TIFF_SHORT:
                    case TIFFDataType.TIFF_SSHORT:
                        // If the tag is also acceptable as a LONG or SLONG
                        // then TIFFSetField will expect an uint parameter
                        // passed to it.
                        //
                        // NB:	We used TIFFFieldWithTag here (see above) knowing that
                        //		it returns us the first entry in the table
                        //		for the tag and that that entry is for the
                        //		widest potential data type the tag may have.
                        TIFFDataType type=fip.field_type;
                        if(type!=TIFFDataType.TIFF_LONG&&type!=TIFFDataType.TIFF_SLONG)
                        {
                            ushort v=(ushort)((tif.tif_header.tiff_magic==TIFF_BIGENDIAN)?(dp.tdir_offset>>tif_typeshift[dp.tdir_type])&tif_typemask[dp.tdir_type]:dp.tdir_offset&tif_typemask[dp.tdir_type]);
                            ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, v):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, v));
                            break;
                        }
                        goto case TIFFDataType.TIFF_LONG; // fall thru...
                    case TIFFDataType.TIFF_LONG:
                    case TIFFDataType.TIFF_SLONG:
                        {
                            uint v32=(uint)((tif.tif_header.tiff_magic==TIFF_BIGENDIAN)?(dp.tdir_offset>>tif_typeshift[dp.tdir_type])&tif_typemask[dp.tdir_type]:dp.tdir_offset&tif_typemask[dp.tdir_type]);
                            ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, v32):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, v32));
                        }
                        break;
                    case TIFFDataType.TIFF_RATIONAL:
                    case TIFFDataType.TIFF_SRATIONAL:
                        {
                            double v=TIFFFetchRational(tif, dp);
                            ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, v):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, v));
                        }
                        break;
                    case TIFFDataType.TIFF_FLOAT:
                        {
                            float v=TIFFFetchFloat(tif, dp);
                            ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, v):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, v));
                        }
                        break;
                    case TIFFDataType.TIFF_DOUBLE:
                        {
                            double v=TIFFFetchDouble(tif, dp);
                            ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, v):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, v));
                        }
                        break;
                    case TIFFDataType.TIFF_ASCII:
                        {
                            string str;
                            ok=TIFFFetchString(tif, dp, out str)!=0;
                            if(ok)
                            {
                                str=str.TrimEnd('\0');
                                str+='\0'; // XXX paranoid
                                ok=(fip.field_passcount?TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, 1, str):TIFFSetField(tif, (TIFFTAG)dp.tdir_tag, (TIFFDataType)dp.tdir_type, str));
                            }
                        }
                        break;
                }
            }
            return ok;
        }
예제 #18
0
        // Fetch a contiguous directory item.
        static int TIFFFetchData(TIFF tif, TIFFDirEntry dir, byte[] cp)
        {
            uint w=(uint)TIFFDataWidth((TIFFDataType)dir.tdir_type);

            // FIXME: butecount should have tsize_t type, but for now libtiff
            // defines tsize_t as a signed 32-bit integer and we are losing
            // ability to read arrays larger than 2^31 bytes. So we are using
            // uint32 instead of tsize_t here.
            uint cc=dir.tdir_count*w;

            // Check for overflow.
            if(dir.tdir_count==0||w==0||cc/w!=dir.tdir_count)
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Error fetching data for field \"{0}\"", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
                return 0;
            }

            if(!SeekOK(tif, dir.tdir_offset))
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Error fetching data for field \"{0}\"", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
                return 0;
            }

            if(!ReadOK(tif, cp, (int)cc))
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Error fetching data for field \"{0}\"", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
                return 0;
            }

            if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)==0) return (int)cc;

            switch((TIFFDataType)dir.tdir_type)
            {
                case TIFFDataType.TIFF_SHORT:
                case TIFFDataType.TIFF_SSHORT:
                    TIFFSwabArrayOfShort(cp, dir.tdir_count);
                    break;
                case TIFFDataType.TIFF_LONG:
                case TIFFDataType.TIFF_SLONG:
                case TIFFDataType.TIFF_FLOAT:
                    TIFFSwabArrayOfLong(cp, dir.tdir_count);
                    break;
                case TIFFDataType.TIFF_RATIONAL:
                case TIFFDataType.TIFF_SRATIONAL:
                    TIFFSwabArrayOfLong(cp, 2*dir.tdir_count);
                    break;
                case TIFFDataType.TIFF_DOUBLE:
                    TIFFSwabArrayOfDouble(cp, dir.tdir_count);
                    break;
            }

            return (int)cc;
        }
예제 #19
0
        // Fetch a rational item from the file
        // at offset off and return the value
        // as a floating point number.
        static double TIFFFetchRational(TIFF tif, TIFFDirEntry dir)
        {
            byte[] buf=new byte[8];
            if(TIFFFetchData(tif, dir, buf)==0) return 1.0;

            double v;
            return !cvtRational(tif, dir, BitConverter.ToUInt32(buf, 0), BitConverter.ToUInt32(buf, 4), out v)?1.0:v;
        }
예제 #20
0
        static int TIFFFetchData(TIFF tif, TIFFDirEntry dir, ushort[] cp)
        {
            byte[] buf=new byte[dir.tdir_count*2];
            int ret=TIFFFetchData(tif, dir, buf);
            if(ret==0) return 0;

            for(int i=0; i<dir.tdir_count; i++) cp[i]=BitConverter.ToUInt16(buf, i*2);
            return ret;
        }
예제 #21
0
        // Fetch and set the RefBlackWhite tag.
        static bool TIFFFetchRefBlackWhite(TIFF tif, TIFFDirEntry dir)
        {
            if(dir.tdir_type==(ushort)TIFFDataType.TIFF_RATIONAL) return TIFFFetchNormalTag(tif, dir);

            // Handle LONG's for backward compatibility.
            uint[] cp=null;
            double[] fp=null;
            try
            {
                cp=new uint[dir.tdir_count];
                fp=new double[dir.tdir_count];
            }
            catch
            {
                TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space for \"ReferenceBlackWhite\" array");
                return false;
            }

            if(!TIFFFetchLongArray(tif, dir, cp)) return false;
            for(int i=0; i<dir.tdir_count; i++) fp[i]=cp[i];
            if(!TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (TIFFDataType)dir.tdir_type, fp)) return false;

            return true;
        }
예제 #22
0
        // Fetch a double item from the file
        // at offset off and return the value.
        static double TIFFFetchDouble(TIFF tif, TIFFDirEntry dir)
        {
            byte[] buf=new byte[8];
            if(TIFFFetchData(tif, dir, buf)==0) return 1.0;

            return BitConverter.ToDouble(buf, 0);
        }
예제 #23
0
        // Fetch a pair of SHORT or BYTE values. Some tags may have either BYTE
        // or SHORT type and this function works with both ones.
        static bool TIFFFetchShortPair(TIFF tif, TIFFDirEntry dir)
        {
            // Prevent overflowing the v stack arrays below by performing a sanity
            // check on tdir_count, this should never be greater than two.
            if(dir.tdir_count>2)
            {
                TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "unexpected count for field \"{0}\", {1}, expected 2; ignored", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name, dir.tdir_count);
                return false;
            }

            switch((TIFFDataType)dir.tdir_type)
            {
                case TIFFDataType.TIFF_BYTE:
                    {
                        byte[] v=new byte[4];
                        return TIFFFetchByteArray(tif, dir, v)&&TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (TIFFDataType)dir.tdir_type, v[0], v[1]);
                    }
                case TIFFDataType.TIFF_SBYTE:
                    {
                        sbyte[] v=new sbyte[4];
                        return TIFFFetchByteArray(tif, dir, v)&&TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (TIFFDataType)dir.tdir_type, v[0], v[1]);
                    }
                case TIFFDataType.TIFF_SHORT:
                    {
                        ushort[] v=new ushort[2];
                        return TIFFFetchShortArray(tif, dir, v)&&TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (TIFFDataType)dir.tdir_type, v[0], v[1]);
                    }
                case TIFFDataType.TIFF_SSHORT:
                    {
                        short[] v=new short[2];
                        return TIFFFetchShortArray(tif, dir, v)&&TIFFSetField(tif, (TIFFTAG)dir.tdir_tag, (TIFFDataType)dir.tdir_type, v[0], v[1]);
                    }
                default: return false;
            }
        }
예제 #24
0
 // Fetch an array of DOUBLE values.
 static bool TIFFFetchDoubleArray(TIFF tif, TIFFDirEntry dir, double[] v)
 {
     byte[] buf=new byte[dir.tdir_count*8];
     if(TIFFFetchData(tif, dir, buf)==0) return false;
     for(int i=0; i<dir.tdir_count; i++) v[i]=BitConverter.ToDouble(buf, i*8);
     return true;
 }
예제 #25
0
        // Fetch a set of offsets or lengths.
        // While this routine says "strips", in fact it's also used for tiles.
        static bool TIFFFetchStripThing(TIFF tif, TIFFDirEntry dir, uint nstrips, ref uint[] lp)
        {
            if(!CheckDirCount(tif, dir, nstrips)) return false;

            // Allocate space for strip information.
            if(lp==null)
            {
                try
                {
                    lp=new uint[nstrips];
                }
                catch
                {
                    TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space for strip array");
                    return false;
                }
            }
            else for(int i=0; i<nstrips; i++) lp[i]=0;

            if(dir.tdir_type==(ushort)TIFFDataType.TIFF_SHORT)
            {
                // Handle uint16=>uint32 expansion.
                ushort[] dp=null;
                try
                {
                    dp=new ushort[dir.tdir_count];
                }
                catch
                {
                    TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to fetch strip tag");
                    return false;
                }

                if(TIFFFetchShortArray(tif, dir, dp))
                {
                    for(int i=0; i<nstrips&&i<(int)dir.tdir_count; i++) lp[i]=dp[i];
                }
                return true;
            }

            if(nstrips!=(int)dir.tdir_count)
            {
                // Special case to incorrect length

                uint[] dp=null;
                try
                {
                    dp=new uint[dir.tdir_count];
                }
                catch
                {
                    TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to fetch strip tag");
                    return false;
                }

                if(TIFFFetchLongArray(tif, dir, dp))
                {
                    for(int i=0; i<nstrips&&i<(int)dir.tdir_count; i++) lp[i]=dp[i];
                }
            }

            return TIFFFetchLongArray(tif, dir, lp);
        }
예제 #26
0
 // Fetch a single floating point value
 // from the offset field and return it
 // as a native float.
 static float TIFFFetchFloat(TIFF tif, TIFFDirEntry dir)
 {
     return BitConverter.ToSingle(BitConverter.GetBytes(dir.tdir_offset), 0);
 }
예제 #27
0
        // Check the count field of a directory
        // entry against a known value. The caller
        // is expected to skip/ignore the tag if
        // there is a mismatch.
        static bool CheckDirCount(TIFF tif, TIFFDirEntry dir, uint count)
        {
            if(count>dir.tdir_count)
            {
                TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "incorrect count for field \"{0}\" ({1}, expecting {2}); tag ignored", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name, dir.tdir_count, count);
                return false;
            }

            if(count<dir.tdir_count)
            {
                TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "incorrect count for field \"{0}\" ({1}, expecting {2}); tag trimmed", TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name, dir.tdir_count, count);
                return true;
            }

            return true;
        }
예제 #28
0
        // Fetch an array of FLOAT values.
        static bool TIFFFetchFloatArray(TIFF tif, TIFFDirEntry dir, float[] v)
        {
            if(dir.tdir_count==1)
            {
                v[0]=BitConverter.ToSingle(BitConverter.GetBytes(dir.tdir_offset), 0);
                return true;
            }

            byte[] buf=new byte[dir.tdir_count*4];
            if(TIFFFetchData(tif, dir, buf)==0) return false;
            for(int i=0; i<dir.tdir_count; i++) v[i]=BitConverter.ToSingle(buf, i*4);
            return true;
        }
예제 #29
0
 // Fetch an array of ANY values. The actual values are
 // returned as doubles which should be able hold all the
 // types. Yes, there really should be an tany_t to avoid
 // this potential non-portability ... Note in particular
 // that we assume that the double return value vector is
 // large enough to read in any fundamental type. We use
 // that vector as a buffer to read in the base type vector
 // and then convert it in place to double (from end
 // to front of course).
 static bool TIFFFetchAnyArray(TIFF tif, TIFFDirEntry dir, double[] v)
 {
     switch((TIFFDataType)dir.tdir_type)
     {
         case TIFFDataType.TIFF_BYTE:
             {
                 byte[] buf=new byte[dir.tdir_count];
                 if(!TIFFFetchByteArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_SBYTE:
             {
                 sbyte[] buf=new sbyte[dir.tdir_count];
                 if(!TIFFFetchByteArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_SHORT:
             {
                 ushort[] buf=new ushort[dir.tdir_count];
                 if(!TIFFFetchShortArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_SSHORT:
             {
                 short[] buf=new short[dir.tdir_count];
                 if(!TIFFFetchShortArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_LONG:
             {
                 uint[] buf=new uint[dir.tdir_count];
                 if(!TIFFFetchLongArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_SLONG:
             {
                 int[] buf=new int[dir.tdir_count];
                 if(!TIFFFetchLongArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_RATIONAL:
         case TIFFDataType.TIFF_SRATIONAL:
             return TIFFFetchRationalArray(tif, dir, v);
         case TIFFDataType.TIFF_FLOAT:
             {
                 float[] buf=new float[dir.tdir_count];
                 if(!TIFFFetchFloatArray(tif, dir, buf)) return false;
                 for(int i=0; i<dir.tdir_count; i++) v[i]=buf[i];
             }
             break;
         case TIFFDataType.TIFF_DOUBLE:
             return TIFFFetchDoubleArray(tif, dir, v);
         default:
             // TIFF_NOTYPE
             // TIFF_ASCII
             // TIFF_UNDEFINED
             TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "cannot read TIFF_ANY type {0} for field \"{1}\"", dir.tdir_type, TIFFFieldWithTag(tif, (TIFFTAG)dir.tdir_tag).field_name);
             return false;
     }
     return true;
 }
예제 #30
0
        // Write/copy data associated with an ASCII or opaque tag value.
        static bool TIFFWriteByteArray(TIFF tif, TIFFDirEntry dir, byte[] cp)
        {
            if(dir.tdir_count<=4)
            {
                //was _TIFFmemcpy(&dir.tdir_offset, cp, dir.tdir_count);
                dir.tdir_offset=0;

                if(tif.tif_header.tiff_magic==TIFF_BIGENDIAN)
                {
                    dir.tdir_offset=(uint)cp[0]<<24;
                    if(dir.tdir_count>=2) dir.tdir_offset|=(uint)cp[1]<<16;
                    if(dir.tdir_count>=3) dir.tdir_offset|=(uint)cp[2]<<8;
                    if(dir.tdir_count==4) dir.tdir_offset|=cp[3];
                }
                else
                {
                    switch(dir.tdir_count)
                    {
                        case 4: dir.tdir_offset=cp[3]; dir.tdir_offset<<=8; goto case 3;
                        case 3: dir.tdir_offset+=cp[2]; dir.tdir_offset<<=8; goto case 2;
                        case 2: dir.tdir_offset+=cp[1]; dir.tdir_offset<<=8; goto case 1;
                        case 1: dir.tdir_offset+=cp[0]; break;
                    }
                }
                return true;
            }

                return TIFFWriteData(tif, dir, cp);
        }