I am trying to create a thumbnail from a PDF file, but I need it to be 300px*300px but no matter what I do I can not get the image to be the correct size. It always seems to be huge.
This is my code:
GhostscriptSettings settings = new GhostscriptSettings();
settings.Page.AllPages = false;
settings.Page.Start = 1;
settings.Page.End = 1;
settings.Size.Native = GhostscriptSharp.Settings.GhostscriptPageSizes.a2;
settings.Device = GhostscriptSharp.Settings.GhostscriptDevices.png16m;
settings.Resolution = new Size(72, 72);
GhostscriptWrapper.GenerateOutput(Path.Combine(FilePath, Filename), FinalPath, settings); // Create the initial thumbnail
Is there any way to output an image with the PPI of 300*300 ?
Cheers,
/r3plica
Looks to me like you are setting a resolution of 300x300. That is 300 dots per inch, which will give you reasonably large files.
You want to change the page size, which looks to me like you are setting to A2. An A2 page at 300 dpi will indeed produce very large output files.....
I have no idea how you would change the media size in C#. The Ghostscript command line switches you need are -dDEVICEWIDTH=300 -dDEVICEHEIGHT=300 -dFIXEDMEDIA
You say you are using a 'PSD' file, which would suggest Photoshop native file format to me, which Ghostscript won't interpret. Possibly you mean a PDF file, in which case you should also add -dPDFFitPage. If on the other hand you mean a PS (PostScript) file, you should set the PageSize Policy to 3 (select nearest media and scale down).
Related
I have combined two images on matlab (3D and binary). I imported both using niftiread and then after I combined both I write them using niftiwrite. However the orientation seems to be wrong for the newly created image. Has anyone encountered this beforehand?
I tried permute, rot, and flip but it did not seem to solve this problem.
The issue is that niftiread only loads the image itself and not the associated metadata that specifies the image orientation (among other things). If you then use niftiwrite without specifying this information, you get default header values.
If the original images on your disk are "3D.nii" and "mask.nii", you would want to do something like:
threeD_info = niftiinfo('3D.nii'); % load metadata for 3D image
threeD_data = niftiread(threeD_info); % load 3D image by specifying info
mask_data = niftiread('mask.nii'); % load mask image by specifying filename
output_data = threeD_data .* mask_data; % multiply images (or other operation of your choice)
niftiwrite(output_data,'3Dmasked.nii',threeD_info); % write output image to 3Dmasked.nii including metadata
Note: Depending on what type of "combination" you are performing, you might need to update some of the fields in threeD_info accordingly, such as the datatype.
So, I'm kind of experimenting with image-manipulation at the byte-level (No 'Image' wrapper or libraries), so the language doesn't matter (I'm using C#) as much as the byte-manipulations, themselves.
I'm now trying to flip a a .jpg image (minus the magic number) over the x- and y-axis, but realized after some trial and error that I think the encoding is getting in the way. This is the code I'm using on a byte[] without the FF D8 or FFD9 includes:
//No magic number included
public class MirrorImgOverXAndYAxes : IFunction
{
//No magic number included
public byte[] Exec(byte[] jpgImage)
{
byte[] resultingImage = new byte[jpgImage.Length];
for (var i = jpgImage.Length - 1; i >= 0; i--)
{
var indexToInsert = jpgImage.Length - 1 - i;
resultingImage[indexToInsert] = jpgImage[i];
}
return resultingImage;
}
}
Right now, my assumption is that it's nowhere near as easy as this, and that I would have to build a full-blown decoder to be able to manipulate the image bytes like this.
Is it possible to create this mirror image without a decoder and would something like what I'm doing work?
Hi I guess just flipping a jpeg by switching the bytes position will not really work here, due to how jpg files are actually structured. if you want to learn more about that, you can look here enter link description here
But you could try to convert the image to a format that actually saves it's pixels within a single byte. For example bitmaps (.bmp).
There is no simple way to do a mirror image that will work in general without decoding.
One problem is that JPEG images are encoded in MCUs that are in turn composed of blocks of eight by eight pixels. For simplicity assume the MCU is an 8x8 block the image width is 15 pixels. That means there will be a dummy column off the edge. If you just flip that, the dummy column will be visible and an image column will be off the edge.
I would like send ZPL instructions to a Zebra printer (GK420t for now).
I'm printing 50mm x 20mm labels.
I would like a logo (small ~ 5mm x 5mm image) to be printed on the upper left corner of the label.
I would like to know the steps I should follow to do this.
I have been reading and trying a few things from the ZPL manual but I don't really understand how it works and couldn't find a working example.
It looks like I have to "load" the image into the printer first (in a so-called "storage area"/DRAM?) and then print it.
The .GRF file extension is mentioned many times in the manual.
I couldn't find the tool to convert a .PNG or .BMP image into a .GRF file.
I read that a .GRF file is an ASCII HEX representation of a graphic image... but it didn't help me do the work.
I could print the logo on the labels using the "Zebra Setup Utilities", by "Downloading Fonts and Graphics", choosing any available .MMF file, adding a .BMP picture, downloading it [to the printer] and printing a test page.
But until now, I couldn't do it using ZPL instructions.
I am also wondering what are the best dimensions I should use given the fact that I need a small image ~5mm x 5mm to be printed on the labels.
The image I printed is a 40px x 40px image.
Also, if I have to make a .GRF file from an original image what should be the type of this file (.BMP, .PNG, .JPG)?
Can you advise me how to proceed?
It sounds like you have some existing ZPL code, and all you want to do is add an image to it.
If that's the case, the easiest solution is probably to go to the Labelary online ZPL viewer, paste your ZPL into the viewer, click "Add image", and upload the image that you want to add to the ZPL.
This should modify your ZPL by adding the image ZPL commands that you need, and you can then tweak the position, etc.
Here is another option: I created my own image to .GRF converter in python. Feel free to use it.
from PIL import Image, ImageOps
import re
import itertools
import numpy as np
# Use: https://www.geeksforgeeks.org/round-to-next-greater-multiple-of-8/
def RoundUp(x, multiple_of = 8):
return ((x + 7) & (-1 * multiple_of))
def image2grf(filePath, width = None, height = None, rotate = None):
image = Image.open(filePath).convert(mode = "1")
#Resize image to desired size
if (width != None):
size = (width, height or width)
if (isinstance(size[0], float)):
size = (int(size[0] * image.width), int(size[1] * image.height))
#Size must be a multiple of 8
size = (RoundUp(size[0]), RoundUp(size[1]))
# image.thumbnail(size, Image.ANTIALIAS)
image = image.resize(size)
if (rotate != None):
image = image.rotate(rotate, expand = True)
image_asArray = np.asarray(np.asarray(image, dtype = 'int'), dtype = 'str').tolist()
bytesPerRow = len(image_asArray[0])
nibblesPerRow = bytesPerRow // 4
totalBytes = nibblesPerRow * len(image_asArray)
#Convert image to hex string
hexString = "".join(
format(int("".join(row[i*4:i*4 + 4]), 2) ^ 0xF, "x")
for row in image_asArray
for i in range(nibblesPerRow)
)
#Compose data
data = "~DGimage," + str(totalBytes // 2) + "," + str(nibblesPerRow // 2) + "," + hexString
#Save image
fileHandle = open(r"labelPicture.grf", "w")
fileHandle.write(data)
fileHandle.close()
if __name__ == '__main__':
# image2grf(r"warning.bmp")
image2grf(r"pallet_label_icons.png", rotate = 90)
Edit: I updated the code above to use my new conversion method, which produces better resolution GRF files
Just install ZebraDesigner, create a blank label, insert a image object to the template and add the required logo image.
Print to File this label (a *.prn file) and open the recently created file with Notepad++ (MS Notepad will ruin the data if opened and saved with). Find a huge string of seemingly random characters, and there is your image's data. Careful not to lose any of those characters, including the control ones, as the whole string is a textual representation of your image (as it would be if it were base64).
Tip0: Always have your ZPLII Programmer's Guide at hand, you'll need/want to check if ZebraDesigner sent the image to memory or directly to the printer buffer.
Tip1: Before adding the logo to the label and get the text, prepare the image making it greyscale (remember to check the printer's dithering configuration!) or, in my case, plain black and white (best result IMHO). The image can be colored, the ZebraDesigner will make it work for the printer converting the image to greyscale before conversion to commands and text.
I created a PHP script to convert PNG images to .GRF similar to Josh Mayberry's image2grf.py:
https://gist.github.com/thomascube/9651d6fa916124a9c52cb0d4262f2c3f
It uses PHP's GD image function and therefore can work with all the file formats GD can open. With small modifications, the Imagick extension could be used but performance seems to be better with GD.
Try codeproject's sharpzebra project. The test program that is part of project prints a graphic and I know this works at least it did on a ZM400
go to Object ==> Picture and your curser will change to something else.. when it changed go and click on the working area and a dialog box iwll apear... so on there select the image so you can see the image whant you wanna print on the printer i am using GT800 so for me i did like that hope this will helps you
Use ZebraNet Bridge Enterprise Software to convert BMP to GRF file format
I had to figure this out again today. In the ZPL code, you can output the graphic bytes for every single label (which means a lot of additional data when you're printing a few thousand labels), or you can define the image first and then refer to it.
I used an online ZPL viewer to save on the number of labels printed when testing. I used:
http://staging.advanced-technology-group.com/
and here is another that does the same:
http://labelary.com/viewer.html
These (currently) have an 'add image' function. This transfers a png to the GRF format that ZPL works with (see the other answers if you need to generate these bytes yourself).
Outputting the bytes for every label
Using the "Add image" function generates a command and the graphic bytes, which looks like:
^FO50,50^GFA,11118,11118,17,,<lots of data>
You can adjust the FO as that tells the printer where to position the graphic.
That should be fine for shorter runs / smaller pictures / you're in a hurry.
Downloading the image once and then referring
This is what I had to do, so I needed to rearrange the bytes a bit (nice pun?).
THe ^GF command stands for Graphic Field: ^GFa,b,c,d,data where
a: A|B (A, non-binary, B = binary)
b: number of bytes transmitted
c: number of bytes comprising the graphic format
d: number of bytes per row
and what I needed to do is to reformat this as ~DGR:000.GRF,11118,17,, so that I could refer to it with ^XGR:000.GRF,1,1. After the print run, I'd need to delete the graphic from memory again with: ^ID000.GRF
The properties for ~DGd:o.x,t,w,data mean
d: memory destination - R for RAM
o: image name (1-8 alphanumeric chars)
x: filename extension, always GRF
t: number of bytes in the graphic
w: number of bytes per row
So I turned:
^FO50,50^GFA,11118,11118,17,,<data>
into:
~DGR:000.GRF,11118,17,,<data>
This definition goes before the label-definition, so:
~DGR:000.GRF,11118,17,,<data>
^XA (start of label)
...
^FT360,700^XGR:000.GRF,1,1^FS <-- this outputs the graphic
...
^XZ (end of label)
^ID000.GRF
I'm using Flying Saucer for HTML to PDF conversion. I need to produce an output PDF with 600dpi in Letter size. How can I achieve this?
There are four different factors at play, and they are all interrelated:
Target Page Metrics
You want the page metrics to be correct, so that when you ask Flying Saucer to produce a "letter" size page, the resulting PDF will show up in Acrobat as measuring 8.5" x 11". You configure the page size directly in FS by specifying the page-size property in your CSS, as obourgain noted in the other answer: #page { size: letter; }
Resolution
You want the final output to be suitable for printing on some printer at a certain XXX dpi. This is all well and good, but remember that PDF is (mostly) a vector format. I didn't check the spec, but as far as I know, the PDF file/page don't "have" resolution because they are vector-based. That having been said, things placed inside the page have an effective resolution, so we'll need your desired XXX dpi number to calculate the numbers below.
Dots per point
In the FlyingSaucer (and Java) world, a point is always a constant 1/72 of an inch. Period. So we can calculate the dots-per-point value by taking the desired resolution and dividing by the size of a point. For example, if you want 300 dpi output:
dots-per-point = 300 dpi / 72 ppi = 300 dots/inch / 72 points/inch = 300/72 dots/point = 4.1666 dots/point
Dots per pixel
This is not a magic number and this value is directly related to the dots-per-point number, as well as the expected resolution of the graphical images that you are trying to feed into FlyingSaucer. More specifically, given a graphic image that is X x Y pixels in dimensions, you need to decide how big you want that to render in your PDF. If you are using an image that was prepared for screen (web) use, you probably are starting out at the standard 96 pixels/inch (so a 96 x 96 px image would render as a one-inch square on the PDF output).
So we can easily calculate dots-per-pixel as follows, again assuming we wanted 300 dpi output:
dots-per-pixel = dots-per-inch (dots) / pixels-per-inch (pixels)
dots-per-pixel = 300 dots/inch / 96 pixels/inch = 3.125 dots/pixel
If you go this approach, your images will be sized correctly, but they won't be the 300 dpi print quality that you're looking for. That's because your images were not of high enough resolution to begin with. More on that in a minute.
Getting it all set up
If you just call SharedContext#setDPI directly as suggested in one of the other answers, you'll likely get the wrong results. This is because it doesn't make logical sense to change the dots-per-point without also changing the resolution (dots-per-inch). The ITextRenderer constructor makes a fixed call to setDPI(72*dotsPerPoint), and when it goes to create a new page, it also uses the dotsPerPoint value set by the constructor to calculate the correct page width in points. If you have changed the resolution under its nose by calling setDPI, you'll end up with the wrong page size.
The correct way is to create a new ITextRenderer object using the values we calculated above. If we wanted 300 dpi output and we had 96 ppi images to feed it, we would call:
ITextRenderer renderer = new ITextRenderer(4.1666f, 3);
Note that the dots-per-pixel parameter only accepts integers, so we're rounding 3.125 to the closest integer above. However...it's truly the ratio between the two numbers that seems to be important, so to make the last argument an integer, we can multiply both numbers by 8 (the lowest integer multiplier that yields an integer), which gives 33.3333 and exactly 25. This also is my guess for the origin of the magic "20" number in the Flying Saucer sources.
Check your output
By this point, your output PDF should look pretty much the same as it did when you started (assuming that you were previously using the default 96 ppi configuration of Flying Saucer). But now we know the parameters that we need to tune to make everything work.
To get high-quality output, you need high quality input
So we've verified that the above parameters work for our purposes, but our images are still a lowly 96 ppi. If we want to print this stuff at high resolution, all you need to do is swap out the images for 300 ppi versions, change the constructor parameters, and then you're done, right?
Maybe. Let's work through the numbers:
Your expected output resolution (300 dpi) does not change, so dots-per-point is still 4.1666. But your input images are now at 300 ppi, so your dots-per-pixel = 300 dots/inch / 300 pixels/inch = 1 dot/pixel. So you'll now call the constructor like this:
ITextRenderer renderer = new ITextRenderer(4.1666f, 1);
Once you do this, your new 300 px x 300 px image will end up as 1" square on the PDF, which is exactly the print quality you wanted.
But wait! All of my text got really small too!
Flying Saucer uses the dots-per-pixel measurement to convert a number of things, not just images. In particular, if you have specified anything in your stylesheets that uses pixels, the dots-per-pixel measurement will have an impact on their sizes too.
If you have stylesheet rules like font-size: 10px; then increasing the dots-per-pixel supplied to the constructor will make that text smaller, which is probably also not what you want. After all, you should be able to increase the resolution of the images in your PDF while leaving your text in the same size and place.
The answer is to convert everything in your stylesheet to use points. (Or inches. At least something other than pixels!) If you started out with the default Flying Saucer settings (meaning pixels are 96 ppi), you simply need to convert all of your "px" measurements into points. Since 72 points = 1 inch, you would change "px" to "pt" and multiply the value by 72/96.
For example, the font-size: 10px; above would become font-size: 7.5pt;. If you want true consistency with what you had before, everything in your CSS that mentions "px" (as well as any inline styles) must be changed into "pt" with the the same conversion too.
Once you have made this change, your text and other layout will be consistent, and if you decide that you need 600 dpi output later, you can just adjust your images and change the constructor argument, but the rest of the layout will still remain constant. Done!
You can set the letter size with the CSS page size property in your HTML document:
#page {
size: letter;
}
You can change the dpi of the document using the following ITextRenderer constructor :
public ITextRenderer(float dotsPerPoint, int dotsPerPixel)
I don't understand what those values really represent, but default values are dotsPerPoint = 20f * 4f / 3f and dotsPerPixel = 20, and it will output a 96dpi document.
To get 600dpi, you can use dotsPerPoint = 500f / 3f and dotsPerPixel = 20.
Looking at the code of ITextRenderer, the final dpi is given by the formula: dpi = dotsPerPoint * 72 / dotsPerPixel.
A simpler answer for setting the DPI when using Flying Saucer:
renderer.getSharedContext().setDPI(600);
As with obourgain's answer, to be used in conjuction with the #page { size:letter; } CSS.
Source
I'm currently creating my figures in matlab to embed themvia latex into a pdf for later printing. I save the figures and save them via the script export_fig! Now I wonder which is the best way to go:
Which size of the matlab figure window to chose
Which -m option to take for the script? It will change the resolution and the size of the image...
I'm wondering about those points in regards to the following two points:
When chosing the figure-size bigger, there are more tickmarks shown and the single point markers are better visible
When using a small figure and using a big -m option, I still have only some tickmarks
When I generate a image which is quite huge (e.g. resolution 300 and still 2000*2000px) and than embed it into the document: Does this than look ugly? Will this be embedded in a nice scaling mode or is it the same ugliness as if you upload a 1000*1000px image onto a homepage and embed it via the widht and height tags in html -> the browser displays it quite ugly because the browser doesn't do a real resize. So it looks unsharp and ugly.
Thanks in advance!
The MATLAB plots are internally described as vector graphics, and PDF files are also described using vector graphics. Rendering the plot to a raster format is a bad idea, because you end up having to choose resolution and end up with bigger files.
Just save the plot to EPS format, which can be directly embedded into a PDF file using latex. I usually save my MATLAB plots for publication using:
saveas(gcf, 'plot.eps', 'epsc');
and embed them directly into my latex file using:
\includegraphics[width=0.7\linewidth]{plot.eps}
Then, you only need to choose the proportion of the line the image is to take (in this case, 70%).
Edit: IrfanView and others (XnView) don't display EPS very well. You can open them in Adobe Illustrator to get a better preview of what it looks like. I always insert my plots this way and they always look exactly the same in the PDF as in MATLAB.
One bonus you also get with EPS is that you can actually specify a font size so that the text is readable even when you resize the image in the document.
As for the number of ticks, you can look at the axes properties in the MATLAB documentation. In particular, the XTick and YTick properties are very useful manually controlling how many ticks appear no matter what the window resolution is.
Edit (again): If you render the image to a raster format (such as PNG), it is preferable to choose the exact same resolution as the one used in the document. Rendering a large image (by using a big window size) and making it small in the PDF will yield bad results mainly because the size of the text will scale directly with the size of the image. Rendering a small image will obviously make for a very bad effect because of stretching.
That is why you should use a vector image format. However, the default MATLAB settings for figures produce some of the same problems as raster images: text size is not specified as a font size and the number of ticks varies with the window size.
To produce optimal plots in the final render, follow the given steps:
Set the figure's font size to a decent setting (e.g. 11pt)
Render the plot
Decide on number of ticks to get a good effect and set the ticks manually
Render the image to color EPS
In MATLAB code, this should look somewhat like the following:
function [] = nice_figure ( render )
%
% invisible figure, good for batch renders.
f = figure('Visible', 'Off');
% make plots look nice in output PDF.
set(f, ...
'DefaultAxesFontSize', 11, ...
'DefaultAxesLineWidth', 0.7, ...
'DefaultLineLineWidth', 0.8, ...
'DefaultPatchLineWidth', 0.7);
% actual plot to render.
a = axes('Parent', f);
% show whatever it is we need to show.
render(a);
% save file.
saveas(f, 'plot.eps', 'epsc');
% collect garbarge.
close(f);
end
Then, you can draw some fancy plot using:
function [] = some_line_plot ( a )
%
% render data.
x = -3 : 0.001 : +3;
y = expm1(x) - x - x.^2;
plot(a, x, y, 'g:');
title('f(x)=e^x-1-x-x^2');
xlabel('x');
ylabel('f(x)');
% force use of 'n' ticks.
n = 5;
xlimit = get(a, 'XLim');
ylimit = get(a, 'YLim');
xticks = linspace(xlimit(1), xlimit(2), n);
yticks = linspace(ylimit(1), ylimit(2), n);
set(a, 'XTick', xticks);
set(a, 'YTick', yticks);
end
And render the final output using:
nice_figure(#some_line_plot);
With such code, you don't need to worry about the window size at all. Notice that I haven't even showed the window for you to play with its size. Using this code, I always get beautiful output and small EPS and PDF file sizes (much smaller than when using PNG).
The only thing this solution does not address is adding more ticks when the plot is made larger in the latex code, but that can't be done anyways.