OS : Win 10
IDE: Visual Studio 2015
Language: C++
Others: I use OpenCV 3.4
I just create a Window Form using CLR empty project,
then put on a pictureBox & three buttons.
First button: load a local image and show on the pictureBox:
pictureBox1->Image = Image::FromFile("D:/something.png");
global_mat = imread("D:/something.png", 1); // global_mat is a global Mat.
zoom_in_counter = 0; // zoom_in_counter is a global int.
Second button: zoom in the image in the pictureBox
if (zoom_in_counter < 5) // You can only enlarge the image 5 times.
{
Mat new_mat = Mat::zeros(0, 0, CV_8UC3);
resize(global_mat, new_mat, cv::Size(global_mat.cols * 2, global_mat.rows * 2));
global_mat = new_mat;
if ((pictureBox1->Width != new_mat.cols) || (pictureBox1->Height != new_mat.rows))
{
pictureBox1->Width = new_mat.cols;
pictureBox1->Height = new_mat.rows;
pictureBox1->Image = gcnew System::Drawing::Bitmap(new_mat.cols, new_mat.rows);
}
System::Drawing::Bitmap^ bmpImage = gcnew Bitmap(
new_mat.cols, new_mat.rows, new_mat.step,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,
System::IntPtr(new_mat.data)
);
Graphics^ g = Graphics::FromImage(pictureBox1->Image);
g->DrawImage(bmpImage, 0, 0, new_mat.cols, new_mat.rows);
pictureBox1->Refresh();
delete g;
zoom_in_counter++;
}
Third buttin: zoom out the image in the pictureBox
if (zoom_in_counter > 0) // You can't shrink the image.
{
Mat new_mat = Mat::zeros(0, 0, CV_8UC3);
resize(global_mat, new_mat, cv::Size(global_mat.cols * 0.5, global_mat.rows * 0.5));
global_mat = new_mat;
if ((pictureBox1->Width != new_mat.cols) || (pictureBox1->Height != new_mat.rows))
{
pictureBox1->Width = new_mat.cols;
pictureBox1->Height = new_mat.rows;
pictureBox1->Image = gcnew System::Drawing::Bitmap(new_mat.cols, new_mat.rows);
}
System::Drawing::Bitmap^ bmpImage = gcnew Bitmap(
new_mat.cols, new_mat.rows, new_mat.step,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,
System::IntPtr(new_mat.data)
);
Graphics^ g = Graphics::FromImage(pictureBox1->Image);
g->DrawImage(bmpImage, 0, 0, new_mat.cols, new_mat.rows);
pictureBox1->Refresh();
delete g;
zoom_in_counter--;
}
And then,
every I zoom in or zoom out, it works,
excludeingthe image is zoomed back to the original size.
I'll get such error message:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
It's really odd!
Finally, my friend figure out what's wrong,
please refer to:
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms536315(v=vs.85).aspx
stride [in]
Type: INT
Integer that specifies the byte offset between the beginning of one scan line and the next. This is usually (but not necessarily) the number of bytes in the pixel format (for example, 2 for 16 bits per pixel) multiplied by the width of the bitmap. The value passed to this parameter must be a multiple of four.
I'm trying to create a blank bitmap in a Xamarin.iOS project using the CGBitmapContext constructor(s). However, no matter what I try I just get the error "System.Exception: Invalid parameters to context creation"
Example code:
const int width = 100;
const int height = 100;
const int bytesPerPixel = 4;
const int bitsPerComponent = 8;
var intBytes = width * height * bytesPerPixel;
byte[] pixelData = new byte[intBytes];
var colourSpace = CGColorSpace.CreateDeviceRGB();
using (var objContext = new CGBitmapContext(pixelData, width, height, bitsPerComponent, width * bytesPerPixel, colourSpace, CGBitmapFlags.ByteOrderDefault))
{
// ...
}
I have tried changing most of the parameters; I tried fixing the data block and passing it as an IntPtr. I tried using null as the first parameter so that the system would allocate the data. And I've tried various flags in the last parameter. I always get that same error. What parameter is wrong? And what needs to be changed in the code above to make it execute?
I changed last parameter from CGBitmapFlags.ByteOrderDefault to CGBitmapFlags.PremultipliedLast , and the error disappear.
refer to CGBitmapFlags Enumeration
As the link said
This enumeration specifies the layout information for the component data in a bitmap.
This enumeration determines the in-memory organization of the data and includes the color model, whether there is an alpha channel present and whether the component values have been premultiplied.
I think we have to select the corresponding flag to match the data info, especially the color model.
For the same reason, If you choose CreateDeviceCmyk , CGBitmapFlags.None will be appropriate.
I am using Epplus library to generate Excel 2010 and up compatible files in Asp.Net C#.
I am using version 3.1.2 which is the latest at this moment.
I am setting the row height first, before adding any pictures like this:
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("sheet 1");
while (i < dt.Rows.Count + offset)
{
ws.Row(i).Height = 84;
i++;
}
dt is my DataTable with DataRows.
After setting the height, I am looping again through the rows to add the pictures
while (i < dt.Rows.Count + offset)
{
var prodImg = ws.Drawings.AddPicture(dr["code"].ToString(), new FileInfo(path));
prodImg.SetPosition(i - 1, 0, 14, 0);
prodImg.SetSize(75);
}
This works, but this does not:
var prodImg = ws.Drawings.AddPicture(dr["code"].ToString(), new FileInfo(path));
int w = prodImg.Image.Width;
int h = prodImg.Image.Height;
if (h > 140) // because height of 84 is 140 pixels in excel
{
double scale = h / 140.0;
w = (int)Math.Floor(w / scale);
h = 140;
}
int xOff = (150 - w) / 2;
int yOff = (140 - h) / 2;
prodImg.SetPosition(i - 1, xOff, 11, yOff);
prodImg.SetSize(w, h);
This results in off center pictures and unresized images. And this code then which is in the same loop:
var prodImgDm = ws.Drawings.AddPicture("bcdm" + dr["code"].ToString(), new FileInfo(pathDm));
prodImgDm.SetPosition(i - 1, 25, 15, 40);
prodImgDm.SetSize(100);
This does work sometimes. the pictures prodImgDm are datamatrix images with a static width and height and do not need to be resized because they are always small/tiny. So also without the SetSize in some rows, it works and in some other rows, it does not work. Really strange because the code is the same. It might be something in the library and/or Excel. Perhaps I am using it wrong? Any epplus picture expert?
Thanks in advance!!
edit sometimes a picture is worth a thousand words, so here is the screenshot. As you can see the product images are not horizontal and vertical aligned in the cell. And the datamatrix on the far right is sometimes scaled about 120% even when I set SetSize(100) so it is really strange to me. So the last datamatrix has the correct size... I already found this SO thread but that does not help me out, I think.
edit 2013/04/09 Essenpillai gave me a hint to set
pck.DoAdjustDrawings = false;
but that gave me even stranger images:
the datamatrix is still changing on row basis. on row is ok, the other is not. and the ean13 code is too wide.
public static void CreatePicture(ExcelWorksheet worksheet, string name, Image image, int firstColumn, int lastColumn, int firstRow, int lastRow, int defaultOffsetPixels)
{
int columnWidth = GetWidthInPixels(worksheet.Cells[firstRow, firstColumn]);
int rowHeight = GetHeightInPixels(worksheet.Cells[firstRow, firstColumn]);
int totalColumnWidth = columnWidth * (lastColumn - firstColumn + 1);
int totalRowHeight = rowHeight * (lastRow - firstRow + 1);
double cellAspectRatio = Convert.ToDouble(totalColumnWidth) / Convert.ToDouble(totalRowHeight);
int imageWidth = image.Width;
int imageHeight = image.Height;
double imageAspectRatio = Convert.ToDouble(imageWidth) / Convert.ToDouble(imageHeight);
int pixelWidth;
int pixelHeight;
if (imageAspectRatio > cellAspectRatio)
{
pixelWidth = totalColumnWidth - defaultOffsetPixels * 2;
pixelHeight = pixelWidth * imageHeight / imageWidth;
}
else
{
pixelHeight = totalRowHeight - defaultOffsetPixels * 2;
pixelWidth = pixelHeight * imageWidth / imageHeight;
}
int rowOffsetPixels = (totalRowHeight - pixelHeight) / 2;
int columnOffsetPixels = (totalColumnWidth - pixelWidth) / 2;
int rowOffsetCount = 0;
int columnOffsetCount = 0;
if (rowOffsetPixels > rowHeight)
{
rowOffsetCount = (int)Math.Floor(Convert.ToDouble(rowOffsetPixels) / Convert.ToDouble(rowHeight));
rowOffsetPixels -= rowHeight * rowOffsetCount;
}
if (columnOffsetPixels > columnWidth)
{
columnOffsetCount = (int)Math.Floor(Convert.ToDouble(columnOffsetPixels) / Convert.ToDouble(columnWidth));
columnOffsetPixels -= columnWidth * columnOffsetCount;
}
int row = firstRow + rowOffsetCount - 1;
int column = firstColumn + columnOffsetCount - 1;
ExcelPicture pic = worksheet.Drawings.AddPicture(name, image);
pic.SetPosition(row, rowOffsetPixels, column, columnOffsetPixels);
pic.SetSize(pixelWidth, pixelHeight);
}
public static int GetHeightInPixels(ExcelRange cell)
{
using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
{
float dpiY = graphics.DpiY;
return (int)(cell.Worksheet.Row(cell.Start.Row).Height * (1 / 72.0) * dpiY);
}
}
public static float MeasureString(string s, Font font)
{
using (var g = Graphics.FromHwnd(IntPtr.Zero))
{
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
return g.MeasureString(s, font, int.MaxValue, StringFormat.GenericTypographic).Width;
}
}
public static int GetWidthInPixels(ExcelRange cell)
{
double columnWidth = cell.Worksheet.Column(cell.Start.Column).Width;
Font font = new Font(cell.Style.Font.Name, cell.Style.Font.Size, FontStyle.Regular);
double pxBaseline = Math.Round(MeasureString("1234567890", font) / 10);
return (int)(columnWidth * pxBaseline);
}
enter image description here
I have the same problem with Epplus library.
After I find no solution how to solve this in my code, I checked source code of this library.
Epplus create excel picture always as twoCellAnchor drawing. In xlsx files you can find drawingXYZ.xml with this code:
<xdr:twoCellAnchor editAs="oneCell">
<xdr:from> ... </xdr:from>
<xdr:to> ... </xdr:to>
<xdr:pic>
...
</xdr:twoCellAnchor>
So, picture is always connected to two cells, and this is not variable part of Epplus library. You can find this part of code in ExcelDrawing.cs file.
XmlElement drawNode = _drawingsXml.CreateElement(
"xdr", "twoCellAnchor", ExcelPackage.schemaSheetDrawings);
colNode.AppendChild(drawNode);
You can easy create your own copy of this dll. The good news is that you need to modify only two files to fix this problem. So..
Download your copy of source codes for Epplus library from this site and open in Visual Studio.
We need to generate code of drawing as oneCellAnchor, so we must remove <xdr:to> element for pictures and create element <xdr:ext /> with picture dimensions as parameters.
New xml structure will looks like:
<xdr:oneCellAnchor editAs="oneCell">
<xdr:from> ... </xdr:from>
<xdr:ext cx="1234567" cy="7654321" />
<xdr:pic>
...
</xdr:oneCellAnchor>
Ok, so, how to do this?
Changes in Epplus code
ExcelDrawings.cs (link to file here)
At first we modify method CreateDrawingXml() inside ExcelDrawings.cs. Order to preserve the original functionality we add an optional parameter (if create oneCellAnchor) with default value. And in method, based this parameter, we create one or tow cell anchor and create or not <xdr:to> element.
Important part of this method code:
private XmlElement CreateDrawingXml(bool twoCell = true) {
if (DrawingXml.OuterXml == "")
{ ... } // not changed
XmlNode colNode= _drawingsXml.SelectSingleNode("//xdr:wsDr", NameSpaceManager);
//First change in method code
XmlElement drawNode;
if (twoCell)
drawNode = _drawingsXml.CreateElement(
"xdr", "twoCellAnchor", ExcelPackage.schemaSheetDrawings);
else
drawNode = _drawingsXml.CreateElement(
"xdr", "oneCellAnchor", ExcelPackage.schemaSheetDrawings);
colNode.AppendChild(drawNode);
//Add from position Element; // Not changed
XmlElement fromNode = _drawingsXml.CreateElement(
"xdr", "from", ExcelPackage.schemaSheetDrawings);
drawNode.AppendChild(fromNode);
fromNode.InnerXml = "<xdr:col>0</xdr:col><xdr:colOff>0</xdr:colOff>"
+ "<xdr:row>0</xdr:row><xdr:rowOff>0</xdr:rowOff>";
//Add to position Element;
//Second change in method
if (twoCell)
{
XmlElement toNode = _drawingsXml.CreateElement(
"xdr", "to", ExcelPackage.schemaSheetDrawings);
drawNode.AppendChild(toNode);
toNode.InnerXml = "<xdr:col>10</xdr:col><xdr:colOff>0</xdr:colOff>"
+ "<xdr:row>10</xdr:row><xdr:rowOff>0</xdr:rowOff>";
}
return drawNode;
}
Then we modify two methods for AddPicture inside the same file:
public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink)
{
if (image != null) {
if (_drawingNames.ContainsKey(Name.ToLower())) {
throw new Exception("Name already exists in the drawings collection");
}
XmlElement drawNode = CreateDrawingXml(false);
// Change: we need create element with dimensions
// like: <xdr:ext cx="3857625" cy="1047750" />
XmlElement xdrext = _drawingsXml.CreateElement(
"xdr", "ext", ExcelPackage.schemaSheetDrawings);
xdrext.SetAttribute("cx",
(image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
xdrext.SetAttribute("cy",
(image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
drawNode.AppendChild(xdrext);
// End of change, next part of method is the same:
drawNode.SetAttribute("editAs", "oneCell");
...
}
}
And this method with FileInfo as input parameter:
public ExcelPicture AddPicture(string Name, FileInfo ImageFile, Uri Hyperlink)
{
if (ImageFile != null) {
if (_drawingNames.ContainsKey(Name.ToLower())) {
throw new Exception("Name already exists in the drawings collection");
}
XmlElement drawNode = CreateDrawingXml(false);
// Change: First create ExcelPicture object and calculate EMU dimensions
ExcelPicture pic = new ExcelPicture(this, drawNode, ImageFile, Hyperlink);
XmlElement xdrext = _drawingsXml.CreateElement(
"xdr", "ext", ExcelPackage.schemaSheetDrawings);
xdrext.SetAttribute("cx",
(pic.Image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
xdrext.SetAttribute("cy",
(pic.Image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
drawNode.AppendChild(xdrext);
// End of change, next part of method is the same (without create pic object)
drawNode.SetAttribute("editAs", "oneCell");
...
}
}
So, this are all important code. Now we must change code for searching nodes and preserve order in elements.
In private void AddDrawings() we change xpath from:
XmlNodeList list = _drawingsXml.SelectNodes(
"//xdr:twoCellAnchor", NameSpaceManager);
To this:
XmlNodeList list = _drawingsXml.SelectNodes(
"//(xdr:twoCellAnchor or xdr:oneCellAnchor)", NameSpaceManager);
It is all in this file, now we change
ExcelPicture.cs (link to file here)
Original code find node for append next code in constructor like this:
node.SelectSingleNode("xdr:to",NameSpaceManager);
Because we do not create <xdr:to> element always, we change this code:
internal ExcelPicture(ExcelDrawings drawings, XmlNode node
, Image image, Uri hyperlink)
: base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/#name")
{
XmlElement picNode = node.OwnerDocument.CreateElement(
"xdr", "pic", ExcelPackage.schemaSheetDrawings);
// Edited: find xdr:to, or xdr:ext if xdr:to not exists
XmlNode befor = node.SelectSingleNode("xdr:to",NameSpaceManager);
if (befor != null && befor.Name == "xdr:to")
node.InsertAfter(picNode, befor);
else {
befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
node.InsertAfter(picNode, befor);
}
// End of change, next part of constructor is unchanged
_hyperlink = hyperlink;
...
}
And the same for second constructor with FileInfo as input parameter:
internal ExcelPicture(ExcelDrawings drawings, XmlNode node
, FileInfo imageFile, Uri hyperlink)
: base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/#name")
{
XmlElement picNode = node.OwnerDocument.CreateElement(
"xdr", "pic", ExcelPackage.schemaSheetDrawings);
// Edited: find xdr:to, or xdr:ext if xdr:to not exists
XmlNode befor = node.SelectSingleNode("xdr:to", NameSpaceManager);
if (befor != null && befor.Name == "xdr:to")
node.InsertAfter(picNode, befor);
else {
befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
node.InsertAfter(picNode, befor);
}
// End of change, next part of constructor is unchanged
_hyperlink = hyperlink;
...
Now, pictures are created as oneCellAnchor. If you want, you can create multiple AddPicture methods for booth variants. Last step is build this project and create your own custom EPPlus.dll. Then close your project which use this dll and copy new files EPPlus.dll, EPPlus.pdb, EPPlus.XML inside your project (backup and replace your original dll files) at the same place (so you don't need do any change in your project references or settings).
Then open and rebuild your project and try if this solve your problem.
Maybe I am too late, but here is mine answer..
you can read it on codeplex issue as well
(https://epplus.codeplex.com/workitem/14846)
I got this problem as well.
And after some research I figured out where the bug is.
It's in the ExcelRow class on the 149 line of code (ExcelRow.cs file).
There is a mistake, when row's Height got changed it recalcs all pictures heights but uses pictures widths inplace of heights, so it's easy to fix.
Just change the line
var pos = _worksheet.Drawings.GetDrawingWidths();
to
var pos = _worksheet.Drawings.GetDrawingHeight();
See the code changes on image
P.S. Actual for version 4.0.4
I need to display the output from Axapta in Excel in the following manner.
Kindly assist.
I have added the following method in my base Excel Class and am able to get the solution.
public void setCellProperty(int _r1, int _c1,int _r2, int _c2,
int _orientation = 0,
int _horizontalAlignment = 1,
int _verticalAlignment = 1,
boolean _wrapText = False,
boolean _addIndent = False,
int _indentLevel = 0,
boolean _shrinkToFit = False,
int _readingOrder = 0,
boolean _mergeCells = False)
{
COM cell1,cell2;
str range;
;
cell1 = null;
cell2 = null;
cell1 = worksheet.cells();
this.variant2COM(cell1, cell1.item(_r1,_c1));
cell2 = worksheet.cells();
this.variant2COM(cell2, cell2.item(_r2,_c2));
range =strfmt("%1:%2",cell1.address(),cell2.address());
cellRange =worksheet.Range(range);
cellRange.Mergecells(_mergeCells);
cellRange.IndentLevel(_indentLevel);
cellRange.AddIndent(_addIndent);
cellRange.Orientation(_orientation);
cellRange.VerticalAlignment(_verticalAlignment);
cellRange.HorizontalAlignment(_horizontalAlignment);
}
the variable _orientation decides the inclination, for the case above pass orientation=90
See this blog on how to export to Excel.
"Rotate a text" is a text formatting option, others are struggling too.
It boils down to whether there is a Excel API, which do that.
Sorry, I can't help you futher.
In WPF there is the FormattedText in the System.Windows.Media namespace MSDN FormattedText that I can use like so:
private static Size GetTextSize(string txt, string font, int size, bool isBold)
{
Typeface tf = new Typeface(new System.Windows.Media.FontFamily(font),
FontStyles.Normal,
(isBold) ? FontWeights.Bold : FontWeights.Normal,
FontStretches.Normal);
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}
Is there a good approach in Silverlight to getting the width in pixels (at the moment height isn't important) besides making a call to the server?
An approach that I've seen used, that may not work in your particular instance, is to throw the text into an unstyled TextBlock, and then get the width of that control, like so:
private double GetTextWidth(string text, int fontSize)
{
TextBlock txtMeasure = new TextBlock();
txtMeasure.FontSize = fontSize;
txtMeasure.Text = text;
double width = txtMeasure.ActualWidth;
return width;
}
It's a hack, no doubt.