public static VersionCheckStatus VersionCheck(int versionNum, int numDataBits, Mode mode, ErrorCorrectionLevel level, string encodingName) { int TotalDataBits = numDataBits; ECISet eciSet = new ECISet(ECISet.AppendOption.NameToValue); if (mode == Mode.EightBitByte) { if (encodingName != DEFAULT_ENCODING) { int eciValue = eciSet.GetECIValueByName(encodingName); TotalDataBits += ECISet.NumOfECIHeaderBits(eciValue); } } int bitCharCountIndicator = CharCountIndicatorTable.GetBitCountInCharCountIndicator(mode, versionNum); TotalDataBits += (4 + bitCharCountIndicator); int expectContainer = DataBits(versionNum, level); int lowerContainer = versionNum == 1 ? 0 : DataBits(versionNum - 1, level); if (expectContainer < TotalDataBits) { return(VersionCheckStatus.SmallerThanExpect); } else if (lowerContainer >= TotalDataBits) { return(VersionCheckStatus.LargerThanExpect); } else { return(VersionCheckStatus.Efficient); } }
/// <summary> /// Decide which version group it belong to /// </summary> /// <param name="numBits">number of bits for bitlist where it contain DataBits encode from input content and ECI header</param> /// <param name="level">Error correction level</param> /// <param name="mode">Mode</param> /// <returns>Version group index for VERSION_GROUP</returns> /// <remarks></remarks> private static int DynamicSearchIndicator(int numBits, ErrorCorrectionLevel level, Mode mode) { int[] charCountIndicator = CharCountIndicatorTable.GetCharCountIndicatorSet(mode); int totalBits = 0; int loopLength = VERSION_GROUP.Length; for (int i = 0; i < loopLength; i++) { totalBits = numBits + NUM_BITS_MODE_INDICATOR + charCountIndicator[i]; QRCodeVersion version = VersionTable.GetVersionByNum(VERSION_GROUP[i]); int numECCodewords = version.GetECBlocksByLevel(level).NumErrorCorrectionCodewards; int dataCodewords = version.TotalCodewords - numECCodewords; if (totalBits <= dataCodewords * 8) { return(i); } } throw new InputOutOfBoundaryException(string.Format("QRCode do not have enough space for {0} bits", (numBits + NUM_BITS_MODE_INDICATOR + charCountIndicator[2]))); }
/// <summary> /// Determine which version to use /// </summary> /// <param name="dataBitsLength">Number of bits for encoded content</param> /// <param name="mode">The mode.</param> /// <param name="level">The level.</param> /// <param name="encodingName">Encoding name for EightBitByte</param> /// <returns>VersionDetail and ECI</returns> /// <remarks></remarks> internal static VersionControlStruct InitialSetup(int dataBitsLength, Mode mode, ErrorCorrectionLevel level, string encodingName) { int totalDataBits = dataBitsLength; bool containECI = false; var eciHeader = new BitList(); //Check ECI header if (mode == Mode.EightBitByte) { if (encodingName != DEFAULT_ENCODING && encodingName != QRCodeConstantVariable.UTF8Encoding) { var eciSet = new ECISet(ECISet.AppendOption.NameToValue); int eciValue = eciSet.GetECIValueByName(encodingName); totalDataBits += ECISet.NumOfECIHeaderBits(eciValue); eciHeader = eciSet.GetECIHeader(encodingName); containECI = true; } } //Determine which version group it belong to int searchGroup = DynamicSearchIndicator(totalDataBits, level, mode); int[] charCountIndicator = CharCountIndicatorTable.GetCharCountIndicatorSet(mode); totalDataBits += (NUM_BITS_MODE_INDICATOR + charCountIndicator[searchGroup]); int lowerSearchBoundary = searchGroup == 0 ? 1 : (VERSION_GROUP[searchGroup - 1] + 1); int higherSearchBoundary = VERSION_GROUP[searchGroup]; //Binary search to find proper version int versionNum = BinarySearch(totalDataBits, level, lowerSearchBoundary, higherSearchBoundary); VersionControlStruct vcStruct = FillVCStruct(versionNum, level, encodingName); vcStruct.isContainECI = containECI; vcStruct.ECIHeader = eciHeader; return(vcStruct); }
/// <summary> /// Decide which version group it belong to /// </summary> /// <param name="numBits">Number of bits for bitlist where it contain DataBits encode from input content and ECI header</param> /// <param name="level">Error correction level</param> /// <returns>Version group index for VERSION_GROUP</returns> private static int DynamicSearchIndicator(int numBits, ErrorCorrectionLevel level) { int[] charCountIndicator = CharCountIndicatorTable.GetCharCountIndicatorSet(); int loopLength = VERSION_GROUP.Length; for (int i = 0; i < loopLength; i++) { int totalBits = numBits + NumBitsModeIndicator + charCountIndicator[i]; QRCodeVersion version = VersionTable.GetVersionByNum(VERSION_GROUP[i]); int numECCodewords = version.GetECBlocksByLevel(level).NumErrorCorrectionCodewards; int dataCodewords = version.TotalCodewords - numECCodewords; if (totalBits <= dataCodewords * 8) { return i; } } throw new InputOutOfBoundaryException($"QRCode do not have enough space for {(numBits + NumBitsModeIndicator + charCountIndicator[2])} bits"); }
/// <summary> /// Determine which version to use /// </summary> /// <param name="dataBitsLength">Number of bits for encoded content</param> /// <param name="encodingName">Encoding name for EightBitByte</param> /// <returns>VersionDetail and ECI</returns> internal static VersionControlStruct InitialSetup(int dataBitsLength, ErrorCorrectionLevel level, string encodingName) { int totalDataBits = dataBitsLength; bool containECI = false; BitList eciHeader = new(); if (encodingName is not DefaultEncoding and not QRCodeConstantVariable.UTF8Encoding) { ECISet eciSet = new(ECISet.AppendOption.NameToValue); int eciValue = eciSet.GetECIValueByName(encodingName); totalDataBits += ECISet.NumOfECIHeaderBits(eciValue); eciHeader = eciSet.GetECIHeader(encodingName); containECI = true; } // Determine which version group it belong to int searchGroup = DynamicSearchIndicator(totalDataBits, level); int[] charCountIndicator = CharCountIndicatorTable.GetCharCountIndicatorSet(); totalDataBits += (NumBitsModeIndicator + charCountIndicator[searchGroup]); int lowerSearchBoundary = searchGroup == 0 ? 1 : (VERSION_GROUP[searchGroup - 1] + 1); int higherSearchBoundary = VERSION_GROUP[searchGroup]; // Binary search to find proper version int versionNum = BinarySearch(totalDataBits, level, lowerSearchBoundary, higherSearchBoundary); VersionControlStruct vcStruct = FillVCStruct(versionNum, level); vcStruct.IsContainECI = containECI; vcStruct.ECIHeader = eciHeader; return(vcStruct); }
protected override int GetBitCountInCharCountIndicator(int version) => CharCountIndicatorTable.GetBitCountInCharCountIndicator(version);