Azure webjob image resize issue - azure

I am using azure web job to save thumb of an image and this is code for doing this
ImageProcessor.Imaging.Formats.FormatBase f;
f = new ImageProcessor.Imaging.Formats.JpegFormat();
Size size = new Size(200, 200);
using (WebClient client = new WebClient())
{
MemoryStream stream = new MemoryStream(client.DownloadData(input));
MemoryStream stream2 = new MemoryStream();
int quality = 110;
do
{
quality = quality - 10;
using (ImageFactory factory = new ImageFactory(false))
{
factory.Load(stream)
.Format(f)
.Resize(size)
//.BackgroundColor(Color.White)
.Quality(quality)
.Save(stream2);
}
} while (stream2.Length > stream.Length || stream2.Length ==100000);
When i add message to queue with this image for example,
job should give me thumb image 200 * 200 but there is trailing black area in top and bottom of resulted image like this which shouldn't be done
Why this is done ???

You're trying to fit a rectangle into a square.
From http://imageprocessor.org/imageprocessor/imagefactory/resize/:
Resize
Resizes the current image to the given dimensions. If EXIF metadata is to be preserved the information contained within will also be updated to match.
public ImageFactory Resize(Size size)
Parameters
size:
The System.Drawing.Size containing the width and height to set the image to.
Passing a 0 for either dimension will omit that dimension.
So, pass in 0 as height to maintain aspect ratio,
Size size = new Size(200, 0);
or use one of the other resize modes: Crop/Min/Max/Stretch

Related

Convert pptx to images using java

i try to write a java program, which converts the pptx to jpeg images. There are many options (e.g., aspose, groupdocs, cloudmersive). But they are limited (either generating images in the evaluation mode or limited by the number of API calls); i prefer an open source library and up till now, i have known 2 libreries which are Apache POI and Docx4j. By using the Apache POI, i was able to implement the conversion PPTX-JPEG; however, the generated images' quality is low even the rendering parameters were set.
// create an empty presentation
public static void Pptx_Img(String slidePath, String outputDir, String fileName) throws Exception {
// create an empty presentation
File file = new File(slidePath);
FileInputStream in = new FileInputStream(file);
XMLSlideShow ppt = new XMLSlideShow(in);
// get the dimension and size of the slide
Dimension pgsize = ppt.getPageSize();
List<XSLFSlide> slides = ppt.getSlides();
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
BufferedImage img = null;
outputDir = outputDir + "\\apache\\pptx\\" + fileName;
Apache.createDirIfNotExists(outputDir);
for (int i = 0; i < 10; i++) {
img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setRenderingHint(Drawable.BUFFERED_IMAGE, new WeakReference<>(img));
// clear area
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
// draw the images
slides.get(i).draw(graphics);
FileOutputStream out = new FileOutputStream(outputDir + "\\slide_" + i + ".jpg");
/*
// specifies where the jpg image has to be written
final ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
writer.setOutput(ImageIO.createImageOutputStream(out));
// writes the file with given compression level
writer.write(null, new IIOImage(img, null, null), jpegParams);
*/
ImageIO.write(img, "jpeg", out);
ppt.write(out);
graphics.dispose();
out.close();
img.flush();
}
System.out.println("Images successfully created");
in.close();
ppt.close();
}
Comparison between the original slide and the generated images
I also came up with another indirect way, which converts pptx-pdf-jpeg (because i have the implementation for conversion pdf-jpeg and the conversion can actually maintain the image quality). But i couldnt find any open source libs which can do the conversion pptx-jpeg. For Apache POI, it can convert pptx-pdf but the mechanism is just similar to pptx-jpeg: writes the Graphic2D-instance to pdf instead of jpeg, which basically does not improve the rendering quality.
Added: Regarding to the comparison, the wrong rendering is also another issue !

POI - Fixed width of image in Excel cell

I followed the approach to add a new image with the POI.
cell.getRow().setHeight(img.getHeightForExcel());
sheet.setColumnWidth(cell.getColumnIndex(), img.getWidthForExcel());
final int picID = workBook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
/* Create the drawing container */
final XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch();
// ========adding image START
final XSSFClientAnchor myAnchor = new XSSFClientAnchor();
myAnchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);
/* Define top left corner, and we can resize picture suitable from there */
myAnchor.setCol1(cell.getColumnIndex()); // Column start
myAnchor.setRow1(rowNum - 1); // Row start
myAnchor.setCol2(cell.getColumnIndex() + 2); // Column end (covers two columns)
myAnchor.setRow2(rowNum); // Row end
/* Invoke createPicture and pass the anchor point and ID */
final XSSFPicture myPicture = drawing.createPicture(myAnchor, picID);
In principal this works quite well. I specify the width of the column at the beginning with the width of the image. (The height as well).
The major problem I'm facing is that as soon as I run autoadjust like
for (; i < max; i++) {
xlsWorkbook.getSheet().autoSizeColumn(i);
}
I get the problem that the first two columns are resized as well. But with this the width of the image is resized as well. Since the width might be quite long (or quite narrow) I don't want to affect the image size.
Is there a way to set the width of the image despite the column width?
If you don't want resizing the image when column widths are changing, then you cannot using that approach. This approach explicitly tells that the image shall be sized as the cell size it is anchored to. So if that cell size changes, the pictures size changes too.
You might think that ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE should protect the image from resizing. But this only is valuable when opened in Excel GUI. Apache poi does not respect ClientAnchor.AnchorType while auto sizing the columns. May be this will change in later versions. But in current version apache poi 5.0.0 it does not.
So to fulfill your requirement you set only a one cell anchor. That is only anchor.setCol1 and anchor.setRow1 as the upper left position of the picture. Then you need resizing the picture later to set the bottom right position. You must do that resizing after all column widths and row heights are set. So after auto sizing the columns. Else the resizing the columns will resizing the picture again.
Complete example:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ImageTest {
public static void main(String[] args) throws Exception {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("My Sample Excel");
//FileInputStream obtains input bytes from the image file
InputStream inputStream = new FileInputStream("./logo.png");
//Get the contents of an InputStream as a byte[].
byte[] bytes = IOUtils.toByteArray(inputStream);
//Adds a picture to the workbook
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
//close the input stream
inputStream.close();
//Returns an object that handles instantiating concrete classes
CreationHelper helper = wb.getCreationHelper();
//Creates the top-level drawing patriarch.
Drawing drawing = sheet.createDrawingPatriarch();
//Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
//Set anchor type; only valuable in Excel GUI
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
//Create an anchor with upper left cell only
anchor.setCol1(1); //Column B
anchor.setRow1(2); //Row 3
//Create a picture
Picture pict = drawing.createPicture(anchor, pictureIdx);
//Reset the image to the original size
//pict.resize(); // don't do this before autosize column
//Create cell in column B to auto sizing that column
Cell cell = sheet.createRow(0).createCell(1);
cell.setCellValue("12345678901234567890");
sheet.autoSizeColumn(1);
//Reset the image to the original size
//pict.resize();
//Reset the image to half the original size
pict.resize(0.5);
//Write the Excel file
FileOutputStream fileOut = null;
fileOut = new FileOutputStream("./myFile.xlsx");
wb.write(fileOut);
fileOut.close();
}
}

How can I prevent my image from changing size when placing it on a spreadsheet (Aspose Cells)?

I have an image that is embedded in my solution and is used on the main form of a Winforms app, and also for pasting into a spreadsheet. The image size is 156X121.
I put it on the sheet like so:
var ms = new MemoryStream();
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable, ms);
Yet when it is on the sheet, it stretches out and spills into neighboring cells, partially obscuring other data:
As you can see, the size is no longer 156X121. The height has been increased by 25%. Why? And how can I prevent that?
This code:
MessageBox.Show(string.Format("image height is {0}", _logo.Height));
MessageBox.Show(string.Format("image width is {0}", _logo.Width));
...showed me "126" as the height and "151" as the width, matching the image as it is in the project. So why is the original size changed? Is there a property I can set to leave the size alone and not stretch it? Or how can I prevent this gumbification of the image?
It's bizarre to me that the image is one size (126X151), its original size is purported to be 1.26" X 1.63", and its size after being scaled is 1.57" X 1.63".
Who or what is allowing this 25% increase in Height?
NOTE: If I select the "Reset" button in the image's "Size and Properties" dialog, it shrinks up as I want it to be, setting the Height "back" to 100% from 125%. Is there a way to do this "Reset" programmatically?
UPDATE
Based on the answer, I tried this:
var ms = new MemoryStream();
//_logo.Height = 121; <= cannot set; Height is a readonly property
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable, ms);
Picture pic = pivotTableSheet.Pictures[0];
//Workbook.Worksheets[0].Pictures[0]; <= does not compile
pic.HeightScale = 100;
pic.WidthScale = 100;
(Workbook.Worksheets[0] does not compile for me).
It makes no difference; the image is still stretching vertically.
UPDATE 2
I realized I needed "Workbook" to be "workBook" due to this:
private static Workbook workBook;
...and so I tried this:
Picture pic = workBook.Worksheets[1].Pictures[0]; // Worksheet 0 is the data sheet that feeds the PivotTable and subsequently gets hidden, so need to use 1
pic.Height = 121;
pic.WidthScale = 100;
...but it still gumbifies the image vertically. So does replacing "pic.Height = 121" with "pic.HeightScale = 100;"
So this is the code currently, which adds the image, but in a vertically gumbified manner:
var ms = new MemoryStream();
//_logo.Height = 121; readonly
_logo.Save(ms, ImageFormat.Png);
ms.Position = 0;
pivotTableSheet.Pictures.Add(0, _grandTotalsColumnPivotTable, ms);
Picture pic = workBook.Worksheets[1].Pictures[0]; // Worksheet 0 is the data sheet that feeds the PivotTable
//pic.Height = 121;
pic.HeightScale = 100;
pic.WidthScale = 100;
Please use this code to reset it to original height.
Picture pic = wb.Worksheets[0].Pictures[0];
pic.HeightScale = 100;
pic.WidthScale = 100;
Note: I am working as Developer Evangelist at Aspose

Bitmap Image: cropping with portrait orientation

Adding camera functionality to my app is killing me! Started with the basic UWP camera sample, but I have to add zooming capability which added a ScrollViewer around the preview control and complicated my life. Found the cropping code in a different sample. Everything works in landscape, but when you rotate the tablet to portrait the cropped image (even without any actual cropping) is rotated 90.
The cropping logic takes originX/Y, ScrollViewer.ViewportWidth/Height & ScrollViewer.ExtentWidth/Height. I don't understand how these values change with the rotation! In Landscape I use topLeft for the X/Y. What would I do for Portrait? I'm setting the width to 400 and in both views it's STILL 400 so I don't believe width/height should be flipped.
Here's the cropping code. Can anyone comment on what should be different for the 2 (actually 4) orientations?
async public static Task<WriteableBitmap> GetCroppedBitmapAsync(StorageFile originalImageFile,
Point startPoint, Size cropSize, Size previewSize)
{
using (IRandomAccessStream stream = await originalImageFile.OpenReadAsync())
{
// Create a decoder from the stream. With the decoder, we can get the properties of the image.
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Adjust the start x/y to the stream size
uint scaledStartPointX = (uint)Math.Round((decoder.PixelWidth * (startPoint.X / previewSize.Width)));
uint scaledStartPointY = (uint)Math.Round((decoder.PixelHeight * (startPoint.Y / previewSize.Height)));
// Now get the scaled size of the viewport (ie the cropped area)
uint selectedAreaWidth = (uint)Math.Round(decoder.PixelWidth * (cropSize.Width / previewSize.Width));
uint selectedAreaHeight = (uint)Math.Round(decoder.PixelHeight * (cropSize.Height / previewSize.Height));
// Get the cropped pixels.
byte[] pixels = await GetPixelData(decoder, scaledStartPointX, scaledStartPointY, selectedAreaWidth, selectedAreaHeight,
decoder.PixelWidth, decoder.PixelHeight);
// Stream the bytes into a WriteableBitmap
WriteableBitmap cropBmp = new WriteableBitmap((int)selectedAreaWidth, (int)selectedAreaHeight);
Stream pixStream = cropBmp.PixelBuffer.AsStream();
pixStream.Write(pixels, 0, (int)(selectedAreaWidth * selectedAreaHeight * 4));
return cropBmp;
}
}

Issues when writing an image

Am into an J2ME project right now where I need to select an image and write this image to a particular folder say somewhere in memory card with a desired file name. Am able to select image and display it but when trying to save it am having trouble. When I try to save, an image file is created but its size is 0.0 kb and when I click on the image it says "File Format not supported"
This is my code
fileCon = (FileConnection)Connector.open(path+"Contacts/contactImages/"+FIRST_NAME+".png",Connector.READ_WRITE);
if(!fileCon.exists())
{
fileCon.create();
}
int h = contactImage.getHeight();
int w = contactImage.getWidth();
int[] size = new int[w*h];
contactImage.getRGB(size, 0, w, 0, 0, w, h);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (int i = 0; i < size.length; i++)
{
dos.writeInt(size[i]);
}
But you are writing pixel data into (in-memory) ByteArrayOutputStream, and not a file stream. Shouldn't there be something like
DataOutputStream dos = fileCon.openDataOutputStream();
And of course output stream should be closed to make sure all data is flushed.
Another thing is that you are saving raw ARGB data and not encoded PNG image, so .png extension may confuse some image viewers. Perhaps .bmp would be better.

Resources