I have the following code:
for (int i = 1; i <= columnArr.Length; i++)
{
sheet.Column(i).AutoFit();
totalWidth += sheet.Column(i).Width;
}
if (image != null)
{
int percent = (int)(totalWidth* 100 / image.Image.Width);
sheet.Row(1).Height = percent * image.Image.Height / 100;
image.SetSize(percent);
}
I want this code should make image (of type ExcelPicture) be as wide as the columns in the relevant part of the sheet (in my case, 3 columns); however, the image is much smaller. However, the row does end up the correct height for the image as shown in the file. How can I fix the width of the image?
You could use the other SetSize method.
SetSize(width, height)
Getting the details right was tricky but this worked for me:
report.Sheet.Column(columnIndex).Width = 10;
report.Sheet.Row(rowIndex).Height = 50;
picture.To.Column = picture.From.Column = columnIndex - 1;
picture.To.Row = picture.From.Row = rowIndex - 1;
picture.SetSize(70, 66);
Note that the column and row index is off by one.
Related
1. Code description: I wrote this app script that for each row, colors the cell in column A the same color as the last cell of that row with text in it. Additionally, I use an onEdit trigger, so whenever I edit a row, the script runs. This worked alright when I had about 20 rows and 20 columns (2-3 seconds).
2. Problem: I now have a sheet with about 200 rows and 20 columns and the code is extremely slow (3-4 minutes or more).
3. QUESTION: How to make it run faster, or, given what I need, should I write this task in another way?
4. Solutions I thought about but don't like:
split my sheet into several sheets (not as helpful for my use case)
add a button to run the app only when I make an edit (not as nice as an onEdit)
5. Code:
function colorFirstCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('courseX');
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var columnFirstCells = 1; // column of cell to be colored
var dataRange = sheet.getRange(1,1, lastRow, lastColumn + 1).getValues();
for(var i = 0; i < lastRow; i++)
{
for(var j = 0; j < lastColumn; j++) {
if(dataRange[i][j] != '' && dataRange[i][j+1] == '') { // cell not empty and cell to the right is empty
var backgroundColor = sheet.getRange(i + 1, j + 1).getBackground(); // get color
sheet.getRange(i + 1, columnFirstCells).setBackground(backgroundColor); // set color
of first col cell
}
}
}
}
I believe your goal is as follows.
You want to reduce the process cost of your script.
In this case, how about the following modification?
Modified script:
function colorFirstCell2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('courseX');
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
var backgrounds = range.getBackgrounds();
var colors = range.getDisplayValues().map((r, i) => {
for (var j = r.length - 1; j >= 0; j--) {
if (r[j] != "") {
return [backgrounds[i][j]];
}
}
return [null];
});
sheet.getRange(1, 1, colors.length).setBackgrounds(colors);
}
In this case, first, the values and background colors are retrieved from the data range. And then, an array including the background colors is created. And, the created array is put to the column "A".
References:
map()
setBackgrounds(color)
I have been doing printing job with Thermal Printer Image Printing on portable thermal printer for weeks and this is code I got for Image Printing.
public static byte[] GetByteImage(Bitmap bm, int BitmapWidth)
{
BitmapData data = GetGreyScaledBitmapData(bm, BitmapWidth);
BitArray dots = data.Dots;
string t = data.Width.ToString();
byte[] width = BitConverter.GetBytes(data.Width);
int offset = 0;
MemoryStream stream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(stream);
//Line spacing
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)0);
while (offset < data.Height)
{
//Declare printer to print image mode
bw.Write((char)0x1B);
bw.Write('*');
bw.Write((byte)33);
bw.Write(width[0]);
bw.Write(width[1]);
for (int x = 0; x < data.Width; ++x)
{
for (int k = 0; k < 3; ++k)
{
byte slice = 0;
for (int b = 0; b < 8; ++b)
{
int y = (((offset / 8) + k) * 8) + b;
int i = (y * data.Width) + x;
bool v = false;
if (i < dots.Length)
{
v = dots[i];
}
slice |= (byte)((v ? 1 : 0) << (7 - b));
}
bw.Write(slice);
}
}
offset += 24;
bw.Write((char)0x0A);
}
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)0);
bw.Flush();
byte[] bytes = stream.ToArray();
return bytes;
}
public static BitmapData GetGreyScaledBitmapData(Bitmap bmpFileName, double imgsize)
{
using (var bitmap = (Bitmap)(bmpFileName))
{
var threshold = 127;
var index = 0;
double multiplier = imgsize;
double scale = (double)(multiplier / (double)bitmap.Width);
int xheight = (int)(bitmap.Height * scale);
int xwidth = (int)(bitmap.Width * scale);
var dimensions = xwidth * xheight;
var dots = new BitArray(dimensions);
for (var y = 0; y < xheight; y++)
{
for (var x = 0; x < xwidth; x++)
{
var _x = (int)(x / scale);
var _y = (int)(y / scale);
Android.Graphics.Color color = new Android.Graphics.Color(bitmap.GetPixel(_x, _y));
var luminance = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
dots[index] = (luminance < threshold);
index++;
}
}
return new BitmapData()
{
Dots = dots,
Height = (int)(bitmap.Height * scale),
Width = (int)(bitmap.Width * scale)
};
}
}
public class BitmapData
{
public BitArray Dots
{
get;
set;
}
public int Height
{
get;
set;
}
public int Width
{
get;
set;
}
}
The problem is, it print very slow and make jerking sound while printing.
Another problem is, the method of image converting to Grey Scale is a bit slow.
And when I test with other apps I found that they have no jerking sound and almost instantly print image after clicked print button.
Is there a way to improve above code so it can print smoothly ?
This is the app I tested Printer Lab - Thermal printer manager
The Thermal Printer I used RPP300 72mm Mobile Printer
The ESC * command you are using prints every 24 dots in height.
Then, as you feel the problem, it will be jerky and slow print.
Please use a combination of GS * and GS / commands to improve it.
Details of their specifications are described on pages 24 to 26 of the Thermal Mobile Printer Command Set Manual.
In Addition:
By the way, I was overlooking another command.
It would be easier for us to create the data that we will send.
However, smooth printing depends on the printer performance and communication line speed.
That command is GS v 0. It is described on pages 32 and 33 of the manual.
The program in this article is a bit image data conversion process for FS q and GS (L / GS 8 L commands, but it can also be used for GS * commands. Please try it.
Convert raster byte[] image data to column Format in C#
Finally got a solution. I was really dumb back then. Just ask your printer manufacturer company for SDK or find SDK from other printer manufacturer.
I want to compare one bitmap with another bitmap (reference bitmap) and draw all the difference of it in resultant bit map.
Using below code I am able to draw only difference area but not with exact color of it.
Here is my code
Bitmap ResultantBitMap = new Bitmap(bitMap1.Height, bitMap2.Height);
BitmapData bitMap1Data = bitMap1.LockBits(new Rectangle(0, 0, bitMap1.Width, bitMap1.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData bitMap2Data = bitMap2.LockBits(new Rectangle(0, 0, bitMap2.Width, bitMap2.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData bitMapResultantData = ResultantBitMap.LockBits(new Rectangle(0, 0, ResultantBitMap.Width, ResultantBitMap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
IntPtr scan0 = bitMap1Data.Scan0;
IntPtr scan02 = bitMap2Data.Scan0;
IntPtr scan0ResImg1 = bitMapResultantData.Scan0;
int bitMap1Stride = bitMap1Data.Stride;
int bitMap2Stride = bitMap2Data.Stride;
int ResultantImageStride = bitMapResultantData.Stride;
for (int y = 0; y < bitMap1.Height; y++)
{
//define the pointers inside the first loop for parallelizing
byte* p = (byte*)scan0.ToPointer();
p += y * bitMap1Stride;
byte* p2 = (byte*)scan02.ToPointer();
p2 += y * bitMap2Stride;
byte* pResImg1 = (byte*)scan0ResImg1.ToPointer();
pResImg1 += y * ResultantImageStride;
for (int x = 0; x < bitMap1.Width; x++)
{
//always get the complete pixel when differences are found
if (Math.Abs(p[0] - p2[0]) >= 20 || Math.Abs(p[1] - p2[1]) >= 20 || Math.Abs(p[2] - p2[2]) >= 20)
{
pResImg1[0] = p2[0];// B
pResImg1[1] = p2[1];//R
pResImg1[2] = p2[2];//G
pResImg1[3] = p2[3];//A (Opacity)
}
p += 4;
p2 += 4;
pResImg1 += 4;
}
}
bitMap1.UnlockBits(bitMap1Data);
bitMap2.UnlockBits(bitMap2Data);
ResultantBitMap.UnlockBits(bitMapResultantData);
ResultantBitMap.Save(#"c:\\abcd\abcd.jpeg");
What I want is the difference image with exact color of the reference image.
It's hard to tell what's going on without knowing what all those library calls and "+= 4" are but, are you sure p and p2 correspond to the first and second images of your diagram?
Also, your "Format32bppArgb" format suggests that [0] corresponds to alpha, not to red. Maybe there's a problem with that, too.
I am trying to make a scrollable table in libgdx. Each row has 4 columns and depending on an integer total number of images in a table increases along with the rows.
I am adding images in a table, which i added to scrollpane and finally the scrollpane is added to another table which is added to the stage.
private void setCards(int row, int columns, int wins) {
//This function adds images to the table
int r ;
if(wins%columns == 0)
r=wins/columns;
else
r = wins/columns + 1;
for (int j = 0; j < r; j++) {
for (int i = 1; i <= columns; i++) {
if (j * columns + i <= wins) {
int k =j*columns+i;
if(k>12)
k= (k%12) + 1;
winningCard = new Texture(Gdx.files.internal("cards/winning_card" + String.valueOf(k)+ ".png"));
Image image = new Image(winningCard);
mTable.add(image).colspan(1).pad(10);
}
else {
scoreCard = new Texture(Gdx.files.internal("cards/score_card.png"));
Image background = new Image(scoreCard);
mTable.add(background).colspan(1).pad(10);
}
mTable.pad(10);
}
mTable.row();
}
}
After this i'm adding the table to scrollpane
mTable.setFillParent(true);
pane = new ScrollPane(mTable);
pane.setScrollingDisabled(true,false);
pane.setScrollBarPositions(true,false);
pane.setFillParent(true);
pane.setClamp(true);
table.add(pane);
table.setFillParent(true);
stage.addActor(table);
The problem i'm facing is, there is a lot of blank space, i have to scroll down to get to the images. I want the screen to start at the first row.
Don't use setFillParent(true) on a table inside a ScrollPane. It causes your problems.
If you want to expand your Table to the size of the scrollpane, use expand()/expandX()/expandY().
So I have to do some operations on part of an image. The operation is not relevant (i dont change this code at all), but the way i create the pointer changes the results i get. I dont understand why that happens.
Why does this code gets the result I want:
for(int row = 0; row < 70; ++row) {
for(int col = 48; col < 208; ++col) {
uchar* p = c.ptr(row+col);
*p = (1-circuloBinario.at<unsigned char>(row,col-48))*(*p) + circuloBinario.at<unsigned char>(row,col-48)*limite;
}
}
And this one doesnt?
for(int row = 0; row < 70; ++row) {
uchar* p = c.ptr(row+48);
for(int col = 48; col < 208; ++col) {
*p = (1-circuloBinario.at<unsigned char>(row,col-48))*(*p) + circuloBinario.at<unsigned char>(row,col-48)*limite;
p++;
}
}
By the way, I dont get any errors with the second code, the problem is that the result I get is not what I expect (it starts modifying the image from a row bigger than 0 and starts from column 0 instead of 48).
Thanks.
Mat::ptr returns a pointer to the specified matrix row.
See the documentation here: http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-ptr
So neither c.ptr(row+col) nor c.ptr(row+48) make sense because you should only be passing a row index to the ptr function.
The way you use Mat::pt is apparently incorrect, as mentioned by M456.
If you want to modify the value of some elements of the matrix, why don't you use the following syntax?
c.at<element_type>(row, col) = new_value;