Realloc() public static method

Allocates new byte array of specified size and copies data from the existing to the new array.
public static Realloc ( byte array, int size ) : byte[]
array byte The existing array.
size int The number of elements in new array.
return byte[]
        /// <summary>
        /// Sets the value(s) of a tag in a TIFF file/stream open for writing.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="value">The tag value(s).</param>
        /// <returns>
        /// <c>true</c> if tag value(s) were set successfully; otherwise, <c>false</c>.
        /// </returns>
        /// <seealso cref="Tiff.SetField"/>
        public virtual bool SetField(Tiff tif, TiffTag tag, FieldValue[] value)
        {
            const string module = "vsetfield";

            TiffDirectory td     = tif.m_dir;
            bool          status = true;
            int           v32    = 0;
            int           v      = 0;

            bool end        = false;
            bool badvalue   = false;
            bool badvalue32 = false;

            switch (tag)
            {
            case TiffTag.SUBFILETYPE:
                td.td_subfiletype = (FileType)value[0].ToByte();
                break;

            case TiffTag.IMAGEWIDTH:
                td.td_imagewidth = value[0].ToInt();
                break;

            case TiffTag.IMAGELENGTH:
                td.td_imagelength = value[0].ToInt();
                break;

            case TiffTag.BITSPERSAMPLE:
                td.td_bitspersample = value[0].ToShort();
                // If the data require post-decoding processing to byte-swap samples, set it
                // up here. Note that since tags are required to be ordered, compression code
                // can override this behavior in the setup method if it wants to roll the post
                // decoding work in with its normal work.
                if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
                {
                    switch (td.td_bitspersample)
                    {
                    case 16:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab16Bit;
                        break;

                    case 24:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab24Bit;
                        break;

                    case 32:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab32Bit;
                        break;

                    case 64:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab64Bit;
                        break;

                    case 128:
                        // two 64's
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab64Bit;
                        break;
                    }
                }
                break;

            case TiffTag.COMPRESSION:
                v = value[0].ToInt() & 0xffff;
                Compression comp = (Compression)v;
                // If we're changing the compression scheme, then notify the previous module
                // so that it can cleanup any state it's setup.
                if (tif.fieldSet(FieldBit.Compression))
                {
                    if (td.td_compression == comp)
                    {
                        break;
                    }

                    tif.m_currentCodec.Cleanup();
                    tif.m_flags &= ~TiffFlags.CODERSETUP;
                }
                // Setup new compression scheme.
                status = tif.setCompressionScheme(comp);
                if (status)
                {
                    td.td_compression = comp;
                }
                else
                {
                    status = false;
                }
                break;

            case TiffTag.PHOTOMETRIC:
                td.td_photometric = (Photometric)value[0].ToInt();
                break;

            case TiffTag.THRESHHOLDING:
                td.td_threshholding = (Threshold)value[0].ToByte();
                break;

            case TiffTag.FILLORDER:
                v = value[0].ToInt();
                FillOrder fo = (FillOrder)v;
                if (fo != FillOrder.LSB2MSB && fo != FillOrder.MSB2LSB)
                {
                    badvalue = true;
                    break;
                }

                td.td_fillorder = fo;
                break;

            case TiffTag.ORIENTATION:
                v = value[0].ToInt();
                Orientation or = (Orientation)v;
                if (or < Orientation.TOPLEFT || Orientation.LEFTBOT < or)
                {
                    badvalue = true;
                    break;
                }
                else
                {
                    td.td_orientation = or;
                }
                break;

            case TiffTag.SAMPLESPERPIXEL:
                // XXX should cross check - e.g. if pallette, then 1
                v = value[0].ToInt();
                if (v == 0)
                {
                    badvalue = true;
                    break;
                }

                td.td_samplesperpixel = (short)v;
                break;

            case TiffTag.ROWSPERSTRIP:
                v32 = value[0].ToInt();
                if (v32 == 0)
                {
                    badvalue32 = true;
                    break;
                }

                td.td_rowsperstrip = v32;
                if (!tif.fieldSet(FieldBit.TileDimensions))
                {
                    td.td_tilelength = v32;
                    td.td_tilewidth  = td.td_imagewidth;
                }
                break;

            case TiffTag.MINSAMPLEVALUE:
                td.td_minsamplevalue = value[0].ToUShort();
                break;

            case TiffTag.MAXSAMPLEVALUE:
                td.td_maxsamplevalue = value[0].ToUShort();
                break;

            case TiffTag.SMINSAMPLEVALUE:
                td.td_sminsamplevalue = value[0].ToDouble();
                break;

            case TiffTag.SMAXSAMPLEVALUE:
                td.td_smaxsamplevalue = value[0].ToDouble();
                break;

            case TiffTag.XRESOLUTION:
                td.td_xresolution = value[0].ToFloat();
                break;

            case TiffTag.YRESOLUTION:
                td.td_yresolution = value[0].ToFloat();
                break;

            case TiffTag.PLANARCONFIG:
                v = value[0].ToInt();
                PlanarConfig pc = (PlanarConfig)v;
                if (pc != PlanarConfig.CONTIG && pc != PlanarConfig.SEPARATE)
                {
                    badvalue = true;
                    break;
                }
                td.td_planarconfig = pc;
                break;

            case TiffTag.XPOSITION:
                td.td_xposition = value[0].ToFloat();
                break;

            case TiffTag.YPOSITION:
                td.td_yposition = value[0].ToFloat();
                break;

            case TiffTag.RESOLUTIONUNIT:
                v = value[0].ToInt();
                ResUnit ru = (ResUnit)v;
                if (ru < ResUnit.NONE || ResUnit.CENTIMETER < ru)
                {
                    badvalue = true;
                    break;
                }

                td.td_resolutionunit = ru;
                break;

            case TiffTag.PAGENUMBER:
                td.td_pagenumber[0] = value[0].ToShort();
                td.td_pagenumber[1] = value[1].ToShort();
                break;

            case TiffTag.HALFTONEHINTS:
                td.td_halftonehints[0] = value[0].ToShort();
                td.td_halftonehints[1] = value[1].ToShort();
                break;

            case TiffTag.COLORMAP:
                v32 = 1 << td.td_bitspersample;
                Tiff.setShortArray(out td.td_colormap[0], value[0].ToShortArray(), v32);
                Tiff.setShortArray(out td.td_colormap[1], value[1].ToShortArray(), v32);
                Tiff.setShortArray(out td.td_colormap[2], value[2].ToShortArray(), v32);
                break;

            case TiffTag.EXTRASAMPLES:
                if (!setExtraSamples(td, ref v, value))
                {
                    badvalue = true;
                    break;
                }

                break;

            case TiffTag.MATTEING:
                if (value[0].ToShort() != 0)
                {
                    td.td_extrasamples = 1;
                }
                else
                {
                    td.td_extrasamples = 0;
                }

                if (td.td_extrasamples != 0)
                {
                    td.td_sampleinfo    = new ExtraSample[1];
                    td.td_sampleinfo[0] = ExtraSample.ASSOCALPHA;
                }
                break;

            case TiffTag.TILEWIDTH:
                v32 = value[0].ToInt();
                if ((v32 % 16) != 0)
                {
                    if (tif.m_mode != Tiff.O_RDONLY)
                    {
                        badvalue32 = true;
                        break;
                    }

                    Tiff.WarningExt(tif, tif.m_clientdata, tif.m_name,
                                    "Nonstandard tile width {0}, convert file", v32);
                }
                td.td_tilewidth = v32;
                tif.m_flags    |= TiffFlags.ISTILED;
                break;

            case TiffTag.TILELENGTH:
                v32 = value[0].ToInt();
                if ((v32 % 16) != 0)
                {
                    if (tif.m_mode != Tiff.O_RDONLY)
                    {
                        badvalue32 = true;
                        break;
                    }

                    Tiff.WarningExt(tif, tif.m_clientdata, tif.m_name,
                                    "Nonstandard tile length {0}, convert file", v32);
                }
                td.td_tilelength = v32;
                tif.m_flags     |= TiffFlags.ISTILED;
                break;

            case TiffTag.TILEDEPTH:
                v32 = value[0].ToInt();
                if (v32 == 0)
                {
                    badvalue32 = true;
                    break;
                }

                td.td_tiledepth = v32;
                break;

            case TiffTag.DATATYPE:
                v = value[0].ToInt();
                SampleFormat sf = SampleFormat.VOID;
                switch (v)
                {
                case DATATYPE_VOID:
                    sf = SampleFormat.VOID;
                    break;

                case DATATYPE_INT:
                    sf = SampleFormat.INT;
                    break;

                case DATATYPE_UINT:
                    sf = SampleFormat.UINT;
                    break;

                case DATATYPE_IEEEFP:
                    sf = SampleFormat.IEEEFP;
                    break;

                default:
                    badvalue = true;
                    break;
                }

                if (!badvalue)
                {
                    td.td_sampleformat = sf;
                }

                break;

            case TiffTag.SAMPLEFORMAT:
                v  = value[0].ToInt();
                sf = (SampleFormat)v;
                if (sf < SampleFormat.UINT || SampleFormat.COMPLEXIEEEFP < sf)
                {
                    badvalue = true;
                    break;
                }

                td.td_sampleformat = sf;

                // Try to fix up the SWAB function for complex data.
                if (td.td_sampleformat == SampleFormat.COMPLEXINT &&
                    td.td_bitspersample == 32 && tif.m_postDecodeMethod == Tiff.PostDecodeMethodType.pdmSwab32Bit)
                {
                    tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab16Bit;
                }
                else if ((td.td_sampleformat == SampleFormat.COMPLEXINT ||
                          td.td_sampleformat == SampleFormat.COMPLEXIEEEFP) &&
                         td.td_bitspersample == 64 && tif.m_postDecodeMethod == Tiff.PostDecodeMethodType.pdmSwab64Bit)
                {
                    tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab32Bit;
                }
                break;

            case TiffTag.IMAGEDEPTH:
                td.td_imagedepth = value[0].ToInt();
                break;

            case TiffTag.SUBIFD:
                if ((tif.m_flags & TiffFlags.INSUBIFD) != TiffFlags.INSUBIFD)
                {
                    td.td_nsubifd = value[0].ToInt();
                    Tiff.setLong8Array(out td.td_subifd, value[1].TolongArray(), td.td_nsubifd);
                }
                else
                {
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Sorry, cannot nest SubIFDs", tif.m_name);
                    status = false;
                }
                break;

            case TiffTag.YCBCRPOSITIONING:
                td.td_ycbcrpositioning = (YCbCrPosition)value[0].ToShort();
                break;

            case TiffTag.YCBCRSUBSAMPLING:
                td.td_ycbcrsubsampling[0] = value[0].ToShort();
                td.td_ycbcrsubsampling[1] = value[1].ToShort();
                break;

            case TiffTag.TRANSFERFUNCTION:
                v = ((td.td_samplesperpixel - td.td_extrasamples) > 1 ? 3 : 1);
                for (int i = 0; i < v; i++)
                {
                    Tiff.setShortArray(out td.td_transferfunction[i], value[0].ToShortArray(), 1 << td.td_bitspersample);
                }
                break;

            case TiffTag.REFERENCEBLACKWHITE:
                // XXX should check for null range
                Tiff.setFloatArray(out td.td_refblackwhite, value[0].ToFloatArray(), 6);
                break;

            case TiffTag.INKNAMES:
                v = value[0].ToInt();
                string s = value[1].ToString();
                v      = checkInkNamesString(tif, v, s);
                status = v > 0;
                if (v > 0)
                {
                    setNString(out td.td_inknames, s, v);
                    td.td_inknameslen = v;
                }
                break;

            default:
                // This can happen if multiple images are open with
                // different codecs which have private tags. The global tag
                // information table may then have tags that are valid for
                // one file but not the other. If the client tries to set a
                // tag that is not valid for the image's codec then we'll
                // arrive here. This happens, for example, when tiffcp is
                // used to convert between compression schemes and
                // codec-specific tags are blindly copied.
                TiffFieldInfo fip = tif.FindFieldInfo(tag, TiffType.ANY);
                if (fip == null || fip.Bit != FieldBit.Custom)
                {
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Invalid {1}tag \"{2}\" (not supported by codec)",
                                  tif.m_name, Tiff.isPseudoTag(tag) ? "pseudo-" : string.Empty,
                                  fip != null ? fip.Name : "Unknown");
                    status = false;
                    break;
                }

                // Find the existing entry for this custom value.
                int tvIndex = -1;
                for (int iCustom = 0; iCustom < td.td_customValueCount; iCustom++)
                {
                    if (td.td_customValues[iCustom].info.Tag == tag)
                    {
                        tvIndex = iCustom;
                        td.td_customValues[iCustom].value = null;
                        break;
                    }
                }

                // Grow the custom list if the entry was not found.
                if (tvIndex == -1)
                {
                    td.td_customValueCount++;
                    TiffTagValue[] new_customValues = Tiff.Realloc(
                        td.td_customValues, td.td_customValueCount - 1, td.td_customValueCount);
                    td.td_customValues = new_customValues;

                    tvIndex = td.td_customValueCount - 1;
                    td.td_customValues[tvIndex].info  = fip;
                    td.td_customValues[tvIndex].value = null;
                    td.td_customValues[tvIndex].count = 0;
                }

                // Set custom value ... save a copy of the custom tag value.
                int tv_size = Tiff.dataSize(fip.Type);
                if (tv_size == 0)
                {
                    status = false;
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Bad field type {1} for \"{2}\"",
                                  tif.m_name, fip.Type, fip.Name);
                    end = true;
                    break;
                }

                int paramIndex = 0;
                if (fip.PassCount)
                {
                    if (fip.WriteCount == TiffFieldInfo.Variable2)
                    {
                        td.td_customValues[tvIndex].count = value[paramIndex++].ToInt();
                    }
                    else
                    {
                        td.td_customValues[tvIndex].count = value[paramIndex++].ToInt();
                    }
                }
                else if (fip.WriteCount == TiffFieldInfo.Variable ||
                         fip.WriteCount == TiffFieldInfo.Variable2)
                {
                    td.td_customValues[tvIndex].count = 1;
                }
                else if (fip.WriteCount == TiffFieldInfo.Spp)
                {
                    td.td_customValues[tvIndex].count = td.td_samplesperpixel;
                }
                else
                {
                    td.td_customValues[tvIndex].count = fip.WriteCount;
                }

                if (fip.Type == TiffType.ASCII)
                {
                    string ascii;
                    Tiff.setString(out ascii, value[paramIndex++].ToString());
                    td.td_customValues[tvIndex].value = Tiff.Latin1Encoding.GetBytes(ascii);
                }
                else
                {
                    td.td_customValues[tvIndex].value = new byte[tv_size * td.td_customValues[tvIndex].count];
                    if ((fip.PassCount ||
                         fip.WriteCount == TiffFieldInfo.Variable ||
                         fip.WriteCount == TiffFieldInfo.Variable2 ||
                         fip.WriteCount == TiffFieldInfo.Spp ||
                         td.td_customValues[tvIndex].count > 1) &&
                        fip.Tag != TiffTag.PAGENUMBER &&
                        fip.Tag != TiffTag.HALFTONEHINTS &&
                        fip.Tag != TiffTag.YCBCRSUBSAMPLING &&
                        fip.Tag != TiffTag.DOTRANGE)
                    {
                        byte[] apBytes = value[paramIndex++].GetBytes();
                        Buffer.BlockCopy(apBytes, 0, td.td_customValues[tvIndex].value, 0, Math.Min(apBytes.Length, td.td_customValues[tvIndex].value.Length));
                    }
                    else
                    {
                        // XXX: The following loop required to handle
                        // PAGENUMBER, HALFTONEHINTS,
                        // YCBCRSUBSAMPLING and DOTRANGE tags.
                        // These tags are actually arrays and should be
                        // passed as arrays to SetField() function, but
                        // actually passed as a list of separate values.
                        // This behavior must be changed in the future!

                        // Upd: This loop also processes some EXIF tags with
                        // UNDEFINED type (like EXIF_FILESOURCE or EXIF_SCENETYPE)
                        // In this case input value is string-based, so
                        // in TiffType.UNDEFINED case we use FieldValue.GetBytes()[0]
                        // construction instead of direct call of FieldValue.ToByte() method.
                        byte[] val    = td.td_customValues[tvIndex].value;
                        int    valPos = 0;
                        for (int i = 0; i < td.td_customValues[tvIndex].count; i++, valPos += tv_size)
                        {
                            switch (fip.Type)
                            {
                            case TiffType.BYTE:
                            case TiffType.UNDEFINED:
                                val[valPos] = value[paramIndex + i].GetBytes()[0];
                                break;

                            case TiffType.SBYTE:
                                val[valPos] = value[paramIndex + i].ToByte();
                                break;

                            case TiffType.SHORT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToShort()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.SSHORT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToShort()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.LONG:
                            case TiffType.IFD:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToInt()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.SLONG:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToInt()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.RATIONAL:
                            case TiffType.SRATIONAL:
                            case TiffType.FLOAT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToFloat()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.DOUBLE:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToDouble()), 0, val, valPos, tv_size);
                                break;

                            default:
                                Array.Clear(val, valPos, tv_size);
                                status = false;
                                break;
                            }
                        }
                    }
                }
                break;
            }

            if (!end && !badvalue && !badvalue32)
            {
                if (status)
                {
                    tif.setFieldBit(tif.FieldWithTag(tag).Bit);
                    tif.m_flags |= TiffFlags.DIRTYDIRECT;
                }
            }

            if (badvalue)
            {
                Tiff.ErrorExt(tif, tif.m_clientdata, module,
                              "{0}: Bad value {1} for \"{2}\" tag",
                              tif.m_name, v, tif.FieldWithTag(tag).Name);
                return(false);
            }

            if (badvalue32)
            {
                Tiff.ErrorExt(tif, tif.m_clientdata, module,
                              "{0}: Bad value {1} for \"{2}\" tag",
                              tif.m_name, v32, tif.FieldWithTag(tag).Name);
                return(false);
            }

            return(status);
        }