Как я могу сделать так, чтобы изображение, используемое в нескольких электронных таблицах Excel, всегда отображалось в полном размере (ячейки Aspose)?

Я использую следующий код для размещения изображения в электронной таблице:

var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
locationWorksheet.Pictures.Add(0, 4, ms);
AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
locationWorksheet.AutoFitRows(options);

Он отлично работает; однако я использую один и тот же код в двух разных отчетах, и изображение отображается в разных размерах. На одном он имеет высоту 0,85 дюйма (63%) и ширину 1,1 дюйма (53%), а на другом — высоту 1,44 дюйма (106%) и ширину 2,07 дюйма (100%).

Почему они должны отличаться по размеру? И почему бы им не быть 100% от исходного размера изображения?

Другой код, который кажется точно таким же (хотя в этом случае столбец, в котором появляется изображение, является динамическим):

var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable - 1, ms);
AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
pivotTableSheet.AutoFitRows(options);

Само изображение в указанном месте имеет высоту 1,35 дюйма и ширину 2,07 дюйма.

Вызывается метод:

internal static Image GetURLImage(string url)
{
    WebClient wc = new WebClient();
    byte[] bytes = wc.DownloadData(url);
    MemoryStream ms = new MemoryStream(bytes);
    return Image.FromStream(ms);
}

Как я могу заставить изображение всегда отображаться на 100% или, по крайней мере, в заданном размере?

ОБНОВИТЬ

У меня также есть (по крайней мере, на данный момент) некоторые отчеты в том же проекте, которые создаются с помощью EPPlus. В них у меня есть следующий код, который позволяет мне установить точный размер изображения:

private void AddImage(ExcelWorksheet oSheet, int rowIndex, int colIndex)
{
    Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
    var excelImage = oSheet.Drawings.AddPicture("PRO*ACT Logo", _logo);
    excelImage.From.Column = colIndex - 1;
    excelImage.From.Row = rowIndex - 1;
    excelImage.SetSize(199, 130);  // 199WX130H is the actual size of the image
    excelImage.From.ColumnOff = Pixel2MTU(2);
    excelImage.From.RowOff = Pixel2MTU(2);
}

... который называется так:

AddImage(deliveryPerformanceWorksheet, UNIT_ROW, LOGO_FIRST_COLUMN);

... но это не будет работать в коде Aspose, потому что лист другого типа - Aspose.Cells.Worksheet вместо ExcelWorksheet, и, таким образом, этот код:

AddImage(locationWorksheet, 0, 4);

... не будет компилироваться в отчете Aspose. Я хотел бы временно преобразовать Aspose.Cells.Worksheet в ExcelWorksheet так же бесцеремонно, как это:

ExcelWorksheet ews = locationWorksheet; // naive attempt to magically morph an Aspose.Cells.Worksheet to an ExcelWorksheet
AddImage(ews, 0, 4);

... так что я мог вызвать AddImage(), но эта вопиющая попытка была остановлена ​​​​свистом компилятора: «Невозможно неявно преобразовать тип« Aspose.Cells.Worksheet »в« OfficeOpenXml.ExcelWorksheet »"

ОБНОВЛЕНИЕ 2

Изображение ожидаемого размера; этот код:

int h = _logo.Height; //130, as expected
int w = _logo.Width; //199, " "

...показано, что изображение было исходного размера. Может ли проблема быть в настройках AutoFitterOptions? Позволяет ли OnlyAuto растягивать/сжимать изображение в зависимости от размера ячейки, в которую оно помещается?

ОБНОВЛЕНИЕ 3

В EPPlus я могу заставить изображения отображаться точно такого же размера, используя этот код:

private void AddImage(ExcelWorksheet oSheet, int rowIndex, int colIndex) 
{
    Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
    var excelImage = oSheet.Drawings.AddPicture("PRO*ACT Logo", _logo);
    excelImage.From.Column = colIndex - 2;
    excelImage.From.Row = rowIndex - 1;
    excelImage.SetSize(199, 130);
    excelImage.From.ColumnOff = Pixel2MTU(2);
    excelImage.From.RowOff = Pixel2MTU(2);
}

... но в Aspose я могу приблизиться только с помощью:

var ms = new MemoryStream();
Image _logo = RoboReporterConstsAndUtils.GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable - 1, ms);

И код EPPlus также сохраняет соотношение высоты и ширины:

Исходное изображение имеет ширину 199 пикселей и высоту 130 пикселей.

Изображения, сжатые EPPlus, имеют размер 1,33 X 2,05, поэтому соотношение 1,5: 1 (близкое приближение) сохраняется.

Однако изображения, сжатые Aspose, имеют размеры 1,63 и 1,67 X 2,07, поэтому соотношение больше похоже на 1,25: 1.

Таким образом, даже если код AutoFitter закомментирован из кода Aspose, изображение все равно либо сжимается по ширине, либо растягивается по высоте.

ОБНОВЛЕНИЕ 4

Основываясь на обсуждении здесь, я попытался это (после копирования изображения в мою папку bin):

int index = locationWorksheet.Pictures.Add(0, 4, 6, 5, "LogoFromSite.png");
Picture pic = locationWorksheet.Pictures[index];
pic.Placement = PlacementType.FreeFloating;

Первые четыре аргумента для [лист].Pictures.Add() — это верхний левый ряд, верхний левый столбец, нижний правый ряд и нижний правый столбец.

Тем не менее, это помещает изображение на странице в нужное место, но затем перемещает его влево на несколько столбцов (!?!)

ОБНОВЛЕНИЕ 5

Я нашел еще один луч надежды здесь и попробовал этот код:

Aspose.Cells.Rendering.ImageOrPrintOptions opts = new Aspose.Cells.Rendering.ImageOrPrintOptions();
opts.OnePagePerSheet = true;
opts.ImageFormat = ImageFormat.Png;
opts.SetDesiredSize(199, 130);

Aspose.Cells.Rendering.SheetRender sr = new Aspose.Cells.Rendering.SheetRender(locationWorksheet, opts);
sr.ToImage(0, "LogoFromSite.png");

... но получил это:

введите здесь описание изображения

Итак: снова раздавил.

ОБНОВЛЕНИЕ 6

Я попробовал некоторый код, предоставленный самими кошками Aspose Cells, но они признали, что с ним есть проблема, и занимались этим. Ради улыбки я попробовал посмотреть, что из этого получится. Этот код:

byte[] bts1 = File.ReadAllBytes("LogoFromSite.png");
byte[] bts2 = File.ReadAllBytes("LogoFromSite.png");

MemoryStream ms1 = new MemoryStream();
ms1.Write(bts1, 0, bts1.Length);
ms1.Position = 0;

//This is for second picture in sheet2
MemoryStream ms2 = new MemoryStream();
ms2.Write(bts2, 0, bts2.Length);
ms2.Position = 0;

//Add picture in first worksheet
int idx = locationWorksheet.Pictures.Add(0, 4, ms1);

//Add picture in second worksheet with original size
idx = locationWorksheet.Pictures.Add(0, 10, ms2);
Picture pic = locationWorksheet.Pictures[idx];
pic.HeightScale = 100;
pic.WidthScale = 100;

... привели к этим «изображениям без изображений»:

введите здесь описание изображения

ОБНОВЛЕНИЕ 7

Я сделал еще одно предприятие; поскольку высота увеличивалась выше и выше 100%, я подумал, что изменю размер изображения на другое и использую это:

var ms = new MemoryStream();
Image _logo = GetURLImage("http://www.proactusa.com/bla/pa_logo_notag.png");

double newHeightDbl = _logo.Height * 0.8;
int newHeightInt = (int)Math.Ceiling(newHeightDbl);
Image resizedImage = ResizeImage(_logo, newHeightInt, _logo.Width);

resizedImage.Save(ms, ImageFormat.Png);
ms.Position = 0;
locationWorksheet.Pictures.Add(0, 4, ms);

...но нет! Он запихивает весь этот хлам в одну жалкую колонку, например:

введите здесь описание изображения

...и гуммифицирует его в изобилии по вертикали, из-за чего он выглядит более тошнотворным, чем смазка на буксире, брошенном бурей.

Вот (украденный/заимствованный) код для изменения размера изображения:

// from http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
        }
    }

    return destImage;
}

person B. Clay Shannon    schedule 02.02.2017    source источник


Ответы (2)


Пожалуйста, проверьте свою тему на форуме Aspose.Cells который отвечает на два ваших следующих вопроса.

1. Можем ли мы повторно использовать один и тот же объект потока памяти, содержащий изображение, в книгах и на листах?

2 - Как добавить картинку оригинального размера?

Примечание. Я работаю разработчиком-евангелистом в Aspose

person shakeel    schedule 06.02.2017

Просто вопрос комментирования кода автоподгонки причудливых штанов:

//AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
//pivotTableSheet.AutoFitRows(options);

Теперь изображение отображается практически в своем реальном размере (но обратите внимание на предостережение ниже); скотч временами «расплывается», но если они на это жалуются, я создам второе изображение и изменю его размер, используя это:

// from http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
        }
    }

    return destImage;
}

Предостережение: это работает достаточно хорошо, поэтому я неохотно принимаю это, но изображения, размещенные на листе, точно не одного размера. Размер одного — 1,67 х 2,07 дюйма, другого — 1,63 х 2,07 дюйма — думаю, достаточно близко для подков, ручных гранат и изображений в таблицах Excel.

person B. Clay Shannon    schedule 02.02.2017