/// <summary> /// 获取匹配数组 /// </summary> /// <param name="array">数组数据</param> /// <param name="isValue">数据匹配器</param> /// <returns>匹配数组</returns> public static /*Type[0]*/ ulong /*Type[0]*/[] getFindArray(this SubArray </*Type[0]*/ ulong /*Type[0]*/> array, Func </*Type[0]*/ ulong /*Type[0]*/, bool> isValue) { if (array.Length == 0) { return(NullValue </*Type[0]*/ ulong /*Type[0]*/> .Array); } int length = ((array.Length + 63) >> 6) << 3; UnmanagedPool pool = UnmanagedPool.GetDefaultPool(length); Pointer.Size data = pool.GetSize64(length); try { Memory.ClearUnsafe(data.ULong, length >> 3); return(FixedArray.GetFindArray(array.Array, array.Start, array.Length, isValue, new MemoryMap(data.Data))); } finally { pool.PushOnly(ref data); } }
/// <summary> /// 添加图片 /// </summary> /// <param name="bitmap">位图</param> /// <param name="leftOffset">X方向偏移量</param> /// <param name="topOffset">Y方向偏移量</param> /// <param name="width">图象宽度</param> /// <param name="height">图象高度</param> /// <param name="bitmapLeftOffset">位图剪切X方向偏移量</param> /// <param name="bitmapTopOffset">位图剪切Y方向偏移量</param> /// <param name="isInterlace">图象数据是否连续方式排列,否则使用顺序排列</param> /// <param name="maxPixel">最大色彩深度</param> /// <returns>图片是否添加成功</returns> internal unsafe bool addImage(BitmapData bitmap, int bitmapLeftOffset, int bitmapTopOffset , int leftOffset, int topOffset, int width, int height, bool isInterlace, byte maxPixel) { if (fileBuffer == null) { return(false); fixed(Color *colorFixed = colors) fixed(int *colorCountFixed = colorCounts) { byte * bitmapFixed = (byte *)bitmap.Scan0, currentBitmap = bitmapFixed + bitmap.Stride * (bitmapTopOffset - 1) + (bitmapLeftOffset + width) * 3; Color *currentColor = colorFixed; int bitMapSpace = bitmap.Stride - (width << 1) - width; colorIndexs.Empty(); for (int colorIndex, row = height; row != 0; --row) { currentBitmap += bitMapSpace; for (int col = width; col != 0; --col) { Color color = new Color { Green = *currentBitmap++, Blue = *currentBitmap++, Red = *currentBitmap++ }; if (colorIndexs.TryGetValue(color, out colorIndex)) { ++colorCountFixed[colorIndex]; } else { colorIndexs.Set(color, colorIndex = (int)(currentColor - colorFixed)); colorCountFixed[colorIndex] = 1; } *currentColor++ = color; } } int pixel = ((uint)colorIndexs.Count).bits() - 1; if ((1 << pixel) != colorIndexs.Count) { ++pixel; } if (pixel > maxPixel) { pixel = maxPixel; } else if (pixel < 2) { pixel = 2; } int maxColorCount = 1 << pixel; fixed(byte *bufferFixed = fileBuffer) { byte *currentBuffer = bufferFixed + bufferIndex; *currentBuffer = 0x2c; *(short *)(currentBuffer + 1) = (short)leftOffset; *(short *)(currentBuffer + 3) = (short)topOffset; *(short *)(currentBuffer + 5) = (short)width; *(short *)(currentBuffer + 7) = (short)height; *(currentBuffer + 9) = (byte)(0x80 + (isInterlace ? 0x40 : 0) + (pixel - 1)); if (!checkBuffer(bufferFixed, 10)) { return(false); } } if (colorIndexs.Count <= maxColorCount) { fixed(byte *bufferFixed = fileBuffer) { int *currentColorCount = colorCountFixed; foreach (Color colorKey in colorIndexs.Keys) { *currentColorCount++ = colorKey.Value; } Color color = new Color(); int currentColorIndex = 0; byte *currentBuffer = bufferFixed + bufferIndex; while (currentColorCount != colorCountFixed) { color.Value = *--currentColorCount; *currentBuffer++ = color.Red; *currentBuffer++ = color.Blue; *currentBuffer++ = color.Green; colorIndexs.Set(color, currentColorIndex++); } *(bufferFixed + bufferIndex + (maxColorCount << 1) + maxColorCount) = (byte)pixel; if (!checkBuffer(bufferFixed, (maxColorCount << 1) + maxColorCount + 1)) { return(false); } } } else { int indexCount = colorIndexs.Count; UnmanagedPool pool = UnmanagedPool.GetDefaultPool(indexCount * sizeof(IntSortIndex)); Pointer.Size sizeBuffer = pool.GetSize(indexCount * (sizeof(IntSortIndex) + sizeof(int))); int * buffer = sizeBuffer.Int; try { IntSortIndex *indexFixed = (IntSortIndex *)(buffer + indexCount), currentSortIndex = indexFixed; foreach (KeyValue <Color, int> colorIndex in colorIndexs.KeyValues) { int color0 = colorIndex.Key.Value; int color3 = ((color0 >> 3) & 0x111111) * 0x1020400; int color2 = ((color0 >> 2) & 0x111111) * 0x1020400; int color1 = ((color0 >> 1) & 0x111111) * 0x1020400; color0 = (color0 & 0x111111) * 0x1020400; (*currentSortIndex++).Set((color3 & 0x70000000) | ((color2 >> 4) & 0x7000000) | ((color1 >> 8) & 0x700000) | ((color0 >> 12) & 0x70000) | ((color3 >> 12) & 0x7000) | ((color2 >> 16) & 0x700) | ((color1 >> 20) & 0x70) | ((color0 >> 24) & 7), colorIndex.Value); } AutoCSer.Algorithm.FixedArrayQuickSort.sort(indexFixed, indexFixed + indexCount - 1); int *currentSortArray; if (maxColorCount != 2) { currentSortArray = buffer; for (int currentColorCode, lastColorCode = (*--currentSortIndex).Value; currentSortIndex != indexFixed; lastColorCode = currentColorCode) { currentColorCode = (*--currentSortIndex).Value; *currentSortArray++ = lastColorCode - currentColorCode; } currentSortArray = buffer + (maxColorCount >> 1) - 2; new AutoCSer.Algorithm.FixedArrayQuickRangeSort.IntRangeSorterDesc { SkipCount = currentSortArray, GetEndIndex = currentSortArray }.Sort(buffer, buffer + indexCount - 2); int minColorDifference = *currentSortArray, minColorDifferenceCount = 1; while (currentSortArray != buffer) { if (*--currentSortArray == minColorDifference) { ++minColorDifferenceCount; } } currentSortIndex = indexFixed + indexCount; int maxCountIndex = (*--currentSortIndex).Index, maxCount = *(colorCountFixed + maxCountIndex); for (int currentColorCode, lastColorCode = (*currentSortIndex).Value; currentSortIndex != indexFixed; lastColorCode = currentColorCode) { currentColorCode = (*--currentSortIndex).Value; int colorDifference = lastColorCode - currentColorCode; if (colorDifference >= minColorDifference) { if (colorDifference == minColorDifference && --minColorDifferenceCount == 0) { ++minColorDifference; } *(colorCountFixed + maxCountIndex) = int.MaxValue; maxCount = *(colorCountFixed + (maxCountIndex = (*currentSortIndex).Index)); } else { int countIndex = (*currentSortIndex).Index, count = *(colorCountFixed + countIndex); if (count > maxCount) { maxCountIndex = countIndex; maxCount = count; } } } *(colorCountFixed + maxCountIndex) = int.MaxValue; } for (currentSortArray = buffer + indexCount, currentSortIndex = indexFixed; currentSortArray != buffer; *(--currentSortArray) = *(colorCountFixed + (*currentSortIndex++).Index)) { ; } currentSortArray = buffer + maxColorCount - 1; new AutoCSer.Algorithm.FixedArrayQuickRangeSort.IntRangeSorterDesc { SkipCount = currentSortArray, GetEndIndex = currentSortArray }.Sort(buffer, buffer + indexCount - 1); int minColorCount = *currentSortArray, minColorCounts = 1; while (currentSortArray != buffer) { if (*--currentSortArray == minColorCount) { ++minColorCounts; } } fixed(byte *fileBufferFixed = fileBuffer) { byte * currentBuffer = fileBufferFixed + bufferIndex; IntSortIndex *lastSortIndex = indexFixed, endSortIndex = indexFixed + indexCount; while (*(colorCountFixed + (*lastSortIndex).Index) < minColorCount) { colorIndexs.Set(*(colorFixed + (*lastSortIndex++).Index), 0); } if (*(colorCountFixed + (*lastSortIndex).Index) == minColorCount && --minColorCounts == 0) { ++minColorCount; } Color outputColor = *(colorFixed + (*lastSortIndex).Index); *currentBuffer++ = outputColor.Red; *currentBuffer++ = outputColor.Blue; *currentBuffer++ = outputColor.Green; colorIndexs.Set(outputColor, 0); for (--maxColorCount; *(colorCountFixed + (*--endSortIndex).Index) < minColorCount; colorIndexs.Set(*(colorFixed + (*endSortIndex).Index), maxColorCount)) { ; } if (*(colorCountFixed + (*endSortIndex).Index) == minColorCount && --minColorCounts == 0) { ++minColorCount; } colorIndexs.Set(*(colorFixed + (*endSortIndex).Index), maxColorCount++); int currentColorIndex = 0; for (int *lastColorCount = colorCountFixed + (*endSortIndex).Index; lastSortIndex != endSortIndex;) { for (*lastColorCount = 0; *(colorCountFixed + (*++lastSortIndex).Index) >= minColorCount; colorIndexs.Set(outputColor, ++currentColorIndex)) { if (*(colorCountFixed + (*lastSortIndex).Index) == minColorCount && --minColorCounts == 0) { ++minColorCount; } outputColor = *(colorFixed + (*lastSortIndex).Index); *currentBuffer++ = outputColor.Red; *currentBuffer++ = outputColor.Blue; *currentBuffer++ = outputColor.Green; } if (lastSortIndex == endSortIndex) { break; } *lastColorCount = int.MaxValue; IntSortIndex *nextSortIndex = lastSortIndex; while (*(colorCountFixed + (*++nextSortIndex).Index) < minColorCount) { ; } for (int lastColorCode = (*(lastSortIndex - 1)).Value, nextColorCode = (*nextSortIndex).Value; lastSortIndex != nextSortIndex; ++lastSortIndex) { colorIndexs.Set(*(colorFixed + (*lastSortIndex).Index), (*lastSortIndex).Value - lastColorCode <= nextColorCode - (*lastSortIndex).Value ? currentColorIndex : (currentColorIndex + 1)); } if (lastSortIndex != endSortIndex) { if (*(colorCountFixed + (*lastSortIndex).Index) == minColorCount && --minColorCounts == 0) { ++minColorCount; } outputColor = *(colorFixed + (*lastSortIndex).Index); *currentBuffer++ = outputColor.Red; *currentBuffer++ = outputColor.Blue; *currentBuffer++ = outputColor.Green; colorIndexs.Set(outputColor, ++currentColorIndex); } } outputColor = *(colorFixed + (*lastSortIndex).Index); *currentBuffer++ = outputColor.Red; *currentBuffer++ = outputColor.Blue; *currentBuffer++ = outputColor.Green; *currentBuffer = (byte)pixel; if (!checkBuffer(fileBufferFixed, (maxColorCount << 1) + maxColorCount + 1)) { return(false); } } } finally { pool.Push(ref sizeBuffer); } } byte *colorIndexFixed = (byte *)colorCountFixed; if (isInterlace) { Color *colorEnd = colorFixed + width * height; int inputSpace = (width << 3) - width; for (Color *inputColor = colorFixed; inputColor < colorEnd; inputColor += inputSpace) { for (Color *inputEnd = inputColor + width; inputColor != inputEnd; *colorIndexFixed++ = (byte)colorIndexs[*inputColor++]) { ; } } for (Color *inputColor = colorFixed + (width << 2); inputColor < colorEnd; inputColor += inputSpace) { for (Color *inputEnd = inputColor + width; inputColor != inputEnd; *colorIndexFixed++ = (byte)colorIndexs[*inputColor++]) { ; } } inputSpace -= width << 2; for (Color *inputColor = colorFixed + (width << 1); inputColor < colorEnd; inputColor += inputSpace) { for (Color *inputEnd = inputColor + width; inputColor != inputEnd; *colorIndexFixed++ = (byte)colorIndexs[*inputColor++]) { ; } } for (Color *inputColor = colorFixed + width; inputColor < colorEnd; inputColor += width) { for (Color *inputEnd = inputColor + width; inputColor != inputEnd; *colorIndexFixed++ = (byte)colorIndexs[*inputColor++]) { ; } } } else { for (Color *inputColor = colorFixed, inputEnd = colorFixed + width * height; inputColor != inputEnd; *colorIndexFixed++ = (byte)colorIndexs[*inputColor++]) { ; } } return(lzwEncode((byte *)colorCountFixed, colorIndexFixed, pixel)); } }