Я ударил кирпичную стену этим ... Я знаю, что мой недостаток как-то в логике, но я объясню, где я нахожусь.
Я (пытаюсь) написать код длядинамически создать квадратное (75x75) эскиз для пиксела для панели навигации в нижней части моего приложения Silverlight.Когда я отлаживаю свой код ниже, я продолжаю получать ошибку «Индекс массива вне границ» во время масштабирования вложенных циклов (я отлаживал только с помощью srcWidth> srcHeight, по одному шагу за раз)
Исходное изображение IЯ тестирую с размером 307x162 (49734 пикселей). Размер dest (для текущей логики) для этого составляет 150x75 (11250 пикселей). Конечно, после этого я намереваюсь обрезать результат до 75x75
.половина через исходное изображение, прежде чем нажать 11251 в качестве индекса пункта назначения.Я знаю, что это моя логика, я просто не знаю, ошибся ли я в размерах, которые я использовал для построения пункта назначения, или в приближениях, использованных при преобразовании чисел с плавающей точкой, или, может быть, это не
Не знаю, именно поэтому я публикую здесь ... во всяком случае, вот мой источник:
private void ResizeNavBarImage(Image src)
{
const int SizeOfRGB = 4;
WriteableBitmap bmpSource = new WriteableBitmap((BitmapSource)src.Source);
int[] iSourcePixels = bmpSource.Pixels;
int srcWidth = bmpSource.PixelWidth;
int srcHeight = bmpSource.PixelHeight;
int destWidth = 75;
int destHeight = 75;
float xFactor = srcWidth / destWidth;
float yFactor = srcHeight / destHeight;
float xSource, ySource;
int iApprox;
int iIndex = 0;
if (srcWidth > srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap((int)(destWidth * yFactor), destHeight);
int[] iDestPixels = bmpDest.Pixels;
// Resize srcHeight to destHeight, srcWidth to same ratio
for (int i = 0; i < srcHeight; i++)
{
for (int j = 0; j < srcWidth; j++)
{
xSource = j * yFactor;
ySource = i * yFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
// Crop half of difference from each side of the width
srcWidth = bmpDest.PixelWidth;
srcHeight = bmpDest.PixelHeight;
int xLeftOffset = (srcWidth - srcHeight) / 2;
WriteableBitmap bmpFinalDest = new WriteableBitmap(destWidth, destHeight);
for (int iPixelRow = 0; iPixelRow < destHeight; iPixelRow++)
{
int srcOffset = (iPixelRow * srcWidth + xLeftOffset) * SizeOfRGB;
int destOffset = iPixelRow * destWidth * SizeOfRGB;
Buffer.BlockCopy(bmpDest.Pixels, srcOffset, bmpFinalDest.Pixels, destOffset, destWidth * SizeOfRGB);
}
src.Source = (ImageSource)bmpFinalDest;
}
else if (srcWidth < srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap(destWidth, (int)(destHeight * xFactor));
int[] iDestPixels = bmpDest.Pixels;
// Resize srcWidth to destWidth, srcHeight to same ratio
for (int i = 0; i < srcHeight; i++)
{
for (int j = 0; j < srcWidth; j++)
{
xSource = j * xFactor;
ySource = i * xFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
// Crop half of difference from each side of the height
srcWidth = bmpDest.PixelWidth;
srcHeight = bmpDest.PixelHeight;
int yTopOffset = (srcHeight - srcWidth) / 2;
WriteableBitmap bmpFinalDest = new WriteableBitmap(destWidth, destHeight);
for (int iPixelRow = yTopOffset; iPixelRow < (destHeight - (yTopOffset * 2)); iPixelRow++)
{
int srcOffset = iPixelRow * srcWidth * SizeOfRGB;
int destOffset = iPixelRow * destWidth * SizeOfRGB;
Buffer.BlockCopy(bmpDest.Pixels, srcOffset, bmpFinalDest.Pixels, destOffset, destWidth * SizeOfRGB);
}
src.Source = (ImageSource)bmpFinalDest;
}
else // (srcWidth == srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap(destWidth, destHeight);
int[] iDestPixels = bmpDest.Pixels;
// Resize and set source
for (var i = 0; i < srcHeight; i++)
{
for (var j = 0; j < srcWidth; j++)
{
xSource = j * xFactor;
ySource = i * yFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
src.Source = (ImageSource)bmpDest;
}
}
===============================================================================
Вот мой рабочий код (с WriteableBitmapEx) для потомков:
private void ResizeNavBarImage(Image src)
{
WriteableBitmap bmpSource = new WriteableBitmap((BitmapSource)src.Source);
int srcWidth = bmpSource.PixelWidth;
int srcHeight = bmpSource.PixelHeight;
int finalDestWidth = 75;
int finalDestHeight = 75;
// Resize
float xFactor = ((float)finalDestWidth / (float)srcWidth);
float yFactor = ((float)finalDestHeight / (float)srcHeight);
float Factor = 0;
if (xFactor < yFactor)
Factor = yFactor;
else
Factor = xFactor;
int destWidth = (int)(srcWidth * Factor);
int destHeight = (int)(srcHeight * Factor);
if (destWidth < destHeight && destWidth != finalDestWidth)
destWidth = finalDestWidth;
else if (destWidth > destHeight && destHeight != finalDestHeight)
destHeight = finalDestHeight;
WriteableBitmap bmpDest = bmpSource.Resize(destWidth, destHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
// Crop
int Offset;
WriteableBitmap bmpFinalDest = new WriteableBitmap(finalDestWidth, finalDestHeight);
if (destWidth > destHeight)
{
Offset = (bmpDest.PixelWidth - bmpDest.PixelHeight) / 2;
if (finalDestWidth % 2 != 0 && Offset % 2 == 0)
Offset -= 1;
bmpFinalDest = bmpDest.Crop(Offset, 0, finalDestWidth, finalDestHeight);
}
else if (destWidth < destHeight)
{
Offset = (bmpDest.PixelHeight - bmpDest.PixelWidth) / 2;
if (finalDestHeight % 2 != 0 && Offset % 2 == 0)
Offset -= 1;
bmpFinalDest = bmpDest.Crop(0, Offset, finalDestWidth, finalDestHeight);
}
else
bmpFinalDest = bmpDest;
src.Source = (ImageSource)bmpFinalDest;
}