Inserting text or html into .notebook - wolfram-mathematica

I would like to insert the output of a web page into a notebook (essentially a text or html "screen capture"). No need for it to be "live", it is just there for reference.
Ideally it would appear much like it does on a web-browser. I want it to be non-evaluatable and I don't want the front end to be trying to format it as a very error ridden Mathematica expression
(EDIT to add: creating a cell and doing "Cell->Convert To->Text Display" is a good-enough way of getting text displayed without the front end reformatting things. I am wondering if this is the "right" way to do this or if there is a better way, especially if I'd like to have html formatting or graphics too)

As far as I know Mathematica isn't able to render HTML pages. Using Import you can get all kinds of things out of html based sites and files. One option is to get a text based version of the site like this:
Import["http://reference.wolfram.com/mathematica/guide/Mathematica.html", "Plaintext"]

If you are on Windows (with .NET), then you could use Mathematica's NETLink functionality in conjunction with the WebBrowser class to capture a screenshot of a web page:
Needs["NETLink`"]
LoadNETType["System.Drawing.Imaging.ImageFormat", AllowShortContext -> False]
LoadNETType["System.Windows.Forms.WebBrowserReadyState", AllowShortContext -> False]
Options[dotNetBrowserScreenshot] = {Width -> 1024, Height -> Automatic};
dotNetBrowserScreenshot[uri_, OptionsPattern[]] :=
NETBlock # Module[{browser, bitmap, tempFile, image, bounds}
, browser = NETNew["System.Windows.Forms.WebBrowser"]
; browser#Width = OptionValue[Width]
; browser#ScrollBarsEnabled = False
; browser#Navigate[uri]
; tempFile = Close#OpenWrite[]
; While[browser#ReadyState =!= System`Windows`Forms`WebBrowserReadyState`Complete
, Pause[0.05]
]
; bounds = browser#Document#Body#ClientRectangle
; browser#Height = OptionValue[Height] /. Automatic -> bounds#Height
; bitmap = NETNew["System.Drawing.Bitmap", browser#Width, browser#Height]
; browser#DrawToBitmap[bitmap, bounds]
; browser#Dispose[]
; bitmap#Save[tempFile, System`Drawing`Imaging`ImageFormat`Png]
; bitmap#Dispose[]
; image = Import[tempFile, "PNG"]
; DeleteFile[tempFile]
; image
]
Sample use:
The complete web page can be captured by using Height -> Automatic (which is the default). Note that the screenshot is being displayed at reduced magnification.

If you just want the text (possibly with styles), select the text on the web page, create a Text cell in Mathematica (cmd-7 on Mac), then paste.

One possibility is to convert the web-page to PDF and then Import this PDF file. This method should give a vector image of the original page that looks similar to what you see in the browser.
Another possibility is to make a screenshot of that web-page in a browser and insert it in the Notebook. It is also possible to make a "screenshot" with higher resolution than your monitor has by printing the web-page on some virtual printer which supports conversion to raster formats (LEADTOOLS ePrint is one of the best).
EDIT
An interesting alternative to making screenshots by hands is to use Google Web page thumbnails service. I do not know much on this but you can get encoded into JavaScript JPEG thumbnail of any web-page with an URL like
http://www.google.com/webpagethumbnail?r=2&f=2&s=300:585&query=wolfram&hl=ru&gl=us&c=11&d=http%3A%2F%2Fintegrals.wolfram.com%2F&b=1&j=google.vs.r&a=D57
This URL gives a file with the following element:
["data:image/jpeg;base64,"]
(<data> here is an acronym for encoded JPEG image data).
We can extract data in Mathematica in the following way:
data = Import[
"http://www.google.com/webpagethumbnail?r=2&f=2&s=300:585&query=\
wolfram&hl=ru&gl=us&c=11&d=http%3A%2F%2Fintegrals.wolfram.com%2F&b=1&\
j=google.vs.r&a=D57"];
imageData =
StringReplace[
data, __ ~~ "[\"data:image/jpeg;base64," ~~ x__ ~~ "\"]," ~~ __ :>
x]
I do not know how to convert imageData further but it is just a matter of knowing of JPEG format specification...

In case you are on OS X, ctrl+shift+cmd+4 results in the cursor changing to a cross with the current coordinates next to it; selecting an arbitrary rectangular area on the screen copies it to the clipboard, from which you can paste it into mma (as a raster graphic).
Surely there exist ways of doing this in other operating systems.

Related

extracting images from PDF with page and screen coordinate information

I want to extract images from PDFs retaining a knowledge of their content (page_number and coordinates on page). (Some tools (e.g. pdfminer) only emit image files with non-semantic names, e.g. Img0.bmp). I can do this with PDFBox (Java) but I'd ideally like a Python tool
My current (arbitrary) designs is to create filenames of the form:
image_<page>_<serial_in_page>_<x1>_<x2>__<y1>_<y2>.png
Currently pdfplumber exposes cooordinates but with a PDFStream and encoding information rather than an image. Code to convert the stream to a *.png would solve the problem.
(NOTE: the pdfplumber approach of rendering to the screen and capturing the known rectangle (which I use) is not a solution as the image is often degraded and frequently overwritten with text.)
(NOTE: I have had problems with several Python tools (pdfminer.six, PuMuPDF) extracting images as they make the background black which obscures black text, etc. PDFBox (Java) doesn't have this problem.)
Python tools are likely to have similar problems to any tools even those that require a single line to manipulate images or extract their details.
Here we can see a visual layout of all the compressed images in the file by using one command line to extract images. Here the individual object references have been converted into normal tiff or jpg (other tools may use pbm and pgm especially for OCR but the result is generally similar). The Greyscale Alpha softmask (B&W) transparency components are not necessarily tied direct to a page or an image other than by internal references, and usually appear like negatives.
What you may note is that the objects that were inserted most likely as one PNG are broken in two when injected into the PDF and their scaled placement is defined. Note that a raw PNG (whatever its source common resolution was) will retain number of dots but its scale when inserted into the PDF could be totally different horizontal and vertical, thus the only meaningful data is W x H in pixel values.
It is not trivial to overlay the mask on the RGB component when simply extracted but can allow for colour changes if desired.
So PDFbox is one of the simpler/better tools for blending to a suitable output, (as you have discovered) but for Python it is generally the top end library products that can identify the placement of the two images and combine into a suitable alpha output like a new PNG.
For many suggestions see Extract images from PDF without resampling, in python?.
Your related part question was knowing where those components are placed on each page since one image (and its alpha mask) could be placed multiple times such as a heading logo on each page. Again it is easy in a single command line to see which pages are referenced by a group of images, but to see which image is placed where requires analyzing each pages resources, again requiring a library interrogation of page contents, thus best done via power house libraries such as iText or any other like PDFtron for python.
For a related command in PyMuPDF see https://pymupdf.readthedocs.io/en/latest/page.html#Page.get_image_rects
I don't have a solution in Python but here is a small script using Ruby and HexaPDF:
require 'hexapdf'
class ImageBorderProcessor < HexaPDF::Content::Processor
def initialize(page, index)
super()
#page = page
#index = index
#count = 0
end
def paint_xobject(name)
super
xobject = resources.xobject(name)
return unless xobject[:Subtype] == :Image
w, h = xobject.width, xobject.height
llx, lly = graphics_state.ctm.evaluate(0, 0)
lrx, lry = graphics_state.ctm.evaluate(1, 0)
urx, ury = graphics_state.ctm.evaluate(1, 1)
ulx, uly = graphics_state.ctm.evaluate(0, 1)
# If the image is rotated, you will need all 4 coordinates, nut just the 2
filename = "image_#{#index}_#{#count}_#{llx}_#{urx}_#{lly}_#{ury}"
xobject.write(filename) rescue puts "Can write image #{#index}-#{#count}"
#count += 1
end
end
doc = HexaPDF::Document.open(ARGV[0])
doc.pages.each_with_index do |page, index|
processor = ImageBorderProcessor.new(page, index)
page.process_contents(processor)
end
It will iterate over all pages of the input document provided on the command line and create files using your file naming scheme. Since HexaPDF doesn't currently support writing all types of PDF images, you might get some error messages for those that can't be written.
If a supported image has an associated image mask defined, it will automatically be used to create a transparent image.
The script will output all images found, even repeated ones. This could easily be changed so that just a soft link is created for repeated images.

How to print a logo on labels using a Zebra printer and sending ZPL instructions to it

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

How to see image data using opencv in visual studio?

I wrote an OPENCV project in VS2010 and the results were not the ones as I expected so I ran the debugger to see where is the problem. When I wanted to see the data inside the image loaded I didn't know how to do it so if I want to see the data inside my images what should I do?
It is pretty simple in matlab for seeing different channel of an image i.e.
a=imread('test.jpg');
p1 = a(:,:,1)
p2 = b(:,:,2)
.
.
In opencv I wrote the same thing but I don't know how to see all the element at once just like Matlab.
a= imread("test.jpg")
split(a,planes);
vector<Mat> T1;
T1 = planes[0];
// How can I see the data inside T1 when debugging the code ?
I think this is what you are looking for - it's a great Visual Studio add-on
https://bitbucket.org/sergiu/opencv-visualizers
Just download the installer, make sure VS is closed, run it, re-open VS and voila! Now, when you point to an OpenCV data structure, all kinds of nice info is showed.
Limitations: I saw some problems with multichannel images (it only shows the first channel) and it also has trouble displaying large matrices. If you want to see raw data in a big matrix, you can use the old good VS trick with debug variables: Stop at a breakpoint, go to Watch tab, and write there
((float*)myMat.data) ,10
Where float is the matrix type, myMat is your matrix, and 10 is the number of values you want to print. It will display the first 10 values at the memory location of myMat.data. If you do not correctly choose the data type, you'll see garbage. In my example, myMat is of type cv::Mat.
And never forget the power of visualizers:
imshow("Image", myMat);
If your data fits into an image. You can use the contrib module's colormap to enhance your visualizers.
I can't actually believe that nobody suggested Image Watch yet. It's the most amazing add-in ever. It shows you a view with all your Mat variables (images (gray and color), matrices) while debugging, there's useful stuff like zooming or contrast-stretching and you can even apply more complex functions directly in the plugin in real-time. It makes debugging of any kind of image operations a breeze and it's immensely helpful if you do calculations and linear algebra stuff with your cv::Mat matrices.
I recommend to use a NativeViewer extension. It actually displays the content of an image in a preview window, not only the properly formatted info.
If you don't want to use a plug-in or extension to Visual Studio, you can access the elements one by one in the debugging watch tab by typing this:
T1.data[T1.step.buf[0]*i + T1.step.buf[1]*j];
where i is the row you want to look at and j is the column.
after downloading imagewatch use the command in watch window
(imagesLoc._Myfirst)[0]
index of image in the vector
You can use the immediate window and the extenshion method like this one
/// <summary>
/// Displays image
/// </summary>
public static void Display (this Mat m, Rect rect = default, string windowName = "")
{
if (string.IsNullOrEmpty(windowName))
{
windowName = m.ToString();
}
var img = rect == default ? m : m.Crop(rect);
double coef = Math.Min(1600d / img.Width, 800d / img.Height);
Cv2.ImShow(windowName, img.Resize(new Size(coef * img.Width, (coef * img.Height) > 1 ? coef * img.Height : 1)));
Cv2.WaitKey();
}
Then you stop at a breakpoint and call yourImage.Display() in the immediate window.
If you can use CLion you can utilize the OpenCV Image Viewer plugin, which displays matrices while debugging just on click.
https://plugins.jetbrains.com/plugin/14371-opencv-image-viewer
Disclaimer: I'm an author of this plugin

Controlling the Rasterize[] width for notebook-related expressions

Update Mr Wizard's answer gives pixel-perfect results, but it is Windows-only and destroys the clipboard contents. My answer should work on any platform, but it's less precise: e.g. it omits In/Out labels. It does allow setting the rasterization width though.
This problem came up when I was trying to make a preview window for an image uploader (see the end of that answer).
I would like to create a palette button that will upload the current notebook selection as an image. Before uploading, I would like to show a preview of the image, to reduce the chance of something going awry before contacting the server.
This is what I have so far (includes only the preview code, not the uploader):
button = Button[
"Preview",
Module[
{expr = NotebookRead#InputNotebook[]},
If[expr =!= {},
With[{img = Rasterize[expr]},
MessageDialog[
Column[{"Would you like to perform the action?", img}],
{"Do it!" :> doIt[img], "Cancel" :> Null}
]
]
]
]
]
In case you are wondering why I used a nested With inside the Module instead of making img a module-variable too: it's because by the time doIt[img] is evaluated, the local module variables will have been cleared, so I need to substitute the rasterized expression directly into the doIt function,
This button works (more or less). You can try it by creating a graphic in the same notebook (e.g. Graphics[Circle[]]), selecting it using a single click, then clicking the Preview button.
However, if I put it in a palette using CreatePalette[button], then the rasterization will happen for the window-width of the palette, and I get something like this:
How can I control the width of rasterization, or more generally, how can I create a preview dialog for the uploader that avoids this issue?
For an additional improvement, it would be nice to be able to size the message window so it fits the preview image (and still shows the button: the button disappears with WindowSize -> All).
Answers
Mr. Wizard's suggestion:
button = Button[
"Preview", (FrontEndExecute[
FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial", "MGF"]];
MessageDialog[
First#Cases[NotebookGet#ClipboardNotebook[],
RasterBox[data_, ___] :>
Image[data, "Byte", ColorSpace -> "RGB", Magnification -> 1],
Infinity]])]
CreatePalette[button]
Problems: It (probably) only works on Windows, and it destroys the clipboard contents.
If it is practical to use the clipboard in this operation you might use: FrontEnd`CopySpecial["MGF"] (copy as bitmap).
I managed to do this by copying the selection to a new notebook, rasterizing the full notebook, then closing it.
CreatePalette#Button["Preview",
Module[{target},
target =
CreateDocument[{}, WindowSelected -> False, Visible -> False];
NotebookWrite[target, NotebookRead[SelectedNotebook[]]];
CreateDialog[{Rasterize[target], DefaultButton[]}];
NotebookClose[target]
]
]
The WindowSize -> 500 option can be added to CreateDocument to set the rasterization width to 500 pixels.
Note some disadvantages (advantages in some cases) of this method compared to copying as bitmap:
Custom styles are lost
In/Out labels are lost
Notebook magnification value is lost
If there's a need, some of these can be remedied by explicitly transferring some notebook options from the SelectedNotebook to the newly created one.
I think this should work without you needing to make a new notebook:
button = Button["Preview",
Module[{expr = NotebookRead#InputNotebook[]},
If[expr =!= {},
With[{img =
Rasterize[expr,
ImageFormattingWidth ->
First#(WindowSize /.
AbsoluteOptions[InputNotebook[], WindowSize])]},
MessageDialog[
Column[{"Would you like to perform the action?",
img}], {"Do it!" :> doIt[img], "Cancel" :> Null},
WindowSize -> {First#ImageDimensions#img, All}]]]]];
CreateDialog[button,
WindowFloating -> True,
WindowClickSelect -> False,
Selectable -> False
]
I used a little option searcher to find ImageFormattingWidth and by passing the image width as the window width you can make the dialog fit the picture nicely and still display the button.
Here's a demo of its results:
Rasterizing a cell from a pallete
Have you tried using ExportString[] to create the graphic into memory? (technically into a temp file, but what do you care:] )
ExportString[your_mathematica_stuff_here,"PNG",Background->None]
See the output on a colored background to verify transparent BG:
Framed[ImportString[ExportString[x^2,"PNG",Background->None]
,"PNG"]
,Background->Yellow]
For images with many color variations (like 3D plots), I recommend JPEG2000 format, and for solid-colored images where transparency is not necessary, use GIF to preserve color detail.
Yes, you can control ImageSize when you export string of the image.

Embedding matlab plot in pdf for printing: Sizes

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.

Resources