Can anyone suggest how to extend page size on one side using postscript? I have to put a mark on a heavy bunch of documents. I use postscript for this (as technology that most native to pdfs, obviously as speed is critical for the task).
I am able to put a mark on the document itself, but I have to add a blank field to the right of each page and this is the problem.
This is what is going on (the mark [copy] is added above the pdf)
This is what has to be (page size extended with blank field on the right):
This is the content of my mark.ps file
<<
/EndPage
{
2 eq { pop false }
{
gsave
7.0 setlinewidth
70 780 newpath moveto
70 900 lineto
120 900 lineto
120 780 lineto
66.5 780 lineto
stroke
closepath
/Helvetica findfont 18 scalefont setfont
newpath
100 792.5 moveto
90 rotate
(COPY) true charpath fill
1 setlinewidth stroke
0 setgray
grestore
true
} ifelse
} bind
>> setpagedevice
This is how it is applied to pdf
gs \
-q \
-dBATCH \
-dNOPAUSE \
-sDEVICE=pdfwrite \
-sOutputFile=output.pdf \
-f mark.ps \
input.pdf
What I tried :
Change page size << /PageSize [595 1642] >> setpagedevice - didnt work
use -g option in gs like this: -g595x1642 - also didnt work fine
If someone has relevant suggestions please share!
Hi I'm wondering how I can scale down / resize a pdf content page per page and my pages could have different size and orientation. My expected result would be a A4 page with the content that best fit to it.
Based on these topics:
How to resize content of PDF without affecting page size?
Using GhostScript to get page size
How to make per-page changes to a pdf document using Ghostscript?
I written a simple code but since I'm really begin with this it is probably not the way to do it.
const script = `
FileName (r) file % open file given by -sFileName
runpdfbegin % open file as pdf
1 1 pdfpagecount { % for each page index
pdfgetpage % get pdf page properties (pushes a dict)
/MediaBox get % get MediaBox value from dict (pushes an array of numbers [ offsetX offsetY width height ])
% Define the new expected height & width
/nheight ${newHeight} def
/nwidth ${newWidth} def
% Destruct the array to the stack
aload pop
/pheight exch def
/pwidth exch def
pop pop
% Compute scales
nheight pheight div % compute scale ratio of height
nwidth pwidth div % compute scale ratio of width
% Now we have the two scale ratio
1 index 1 index lt
{ % if scaleY < scaleX
pop
}
{
exch
pop
}
ifelse
/pscale exch def
% At this stage I have the min scale
% Compute translateX
pwidth pscale pwidth % (WIDTH - (scale * WIDTH)) / 2
mul sub 2 div round
/ptranslateX exch def
% Compute translateY
pheight pscale pheight % (HEIGHT - (scale * HEIGHT)) / 2
mul sub 2 div round
/ptranslateY exch def
% Now build the scale and translate operation
<</BeginPage{pscale pscale scale ptranslateX ptranslateY translate}>> setpagedevice
} for`
// Resize the page
await spawnProcess('gs', [
'-sDEVICE=pdfwrite',
'-dPDFSETTINGS=/ebook',
'-dCompatibilityLevel=1.5',
'-dSubsetFonts=true',
'-dEmbedAllFonts=true',
'-dFIXEDMEDIA',
'-dSAFER',
'-dNOPAUSE',
'-dBATCH',
'-dUNROLLFORMS',
'-dAutoRotatePages=/PageByPage',
'-dFitPage',
`-sOutputFile=${filename}-resized.pdf`,
`-dDEVICEWIDTHPOINTS=595`,
`-dDEVICEHEIGHTPOINTS=842`,
// '-c', `<</BeginPage{${scale} ${scale} scale ${translateX} ${translateY} translate}>> setpagedevice`,
'-c', script,
'-sFileName', filename
])
Note: Using ghostscript -dFitPage option works on some pdf but not all of them in contrary to -c "<</BeginPage{${scale} ${scale} scale ${translateX} ${translateY} translate}>> setpagedevice" that works on all the pdfs I tested but does not fit page per page. That's why I'm trying to do a custom script.
It would be great if you could help me to be on the right way
I have a code that converts image from nv12 to yuv444
for h in range(self.img_shape[0]):
# centralize yuv 444 data for inference framework
for w in range(self.img_shape[1]):
yuv444_res[h][w][0] = (nv12_y_data[h * self.img_shape[1] +w]).astype(np.int8)
yuv444_res[h][w][1] = (nv12_u_data[int(h / 2) * int(self.img_shape[1] / 2) +int(w / 2)]).astype(np.int8)
yuv444_res[h][w][2] = (nv12_v_data[int(h / 2) * int(self.img_shape[1] / 2) +int(w / 2)]).astype(np.int8)
Since for loop is very slow in python, much slower than numpy. I was wondering if this conversion can be done in NumPy calculation.
Update on 06/15/2021:
I was able to get this piece of code with fancy indexing from this page External Link:
yuv444 = np.empty([self.height, self.width, 3], dtype=np.uint8)
yuv444[:, :, 0] = nv12_data[:self.width * self.height].reshape(
self.height, self.width)
u = nv12_data[self.width * self.height::2].reshape(
self.height // 2, self.width // 2)
yuv444[:, :, 1] = Image.fromarray(u).resize((self.width, self.height))
v = nv12_data[self.width * self.height + 1::2].reshape(
self.height // 2, self.width // 2)
yuv444[:, :, 2] = Image.fromarray(v).resize((self.width, self.height))
data[0] = yuv444.astype(np.int8)
If the PIL is used to replace the deprecated imresize, then the code match the old code 100%
Update on 06/19/2021:
After a closer look at the answer Rotem given, I realize that his way is quicker.
#nv12_data is reshaped to one dimension
y = nv12_data[:self.width * self.height].reshape(
self.height, self.width)
shrunk_u = nv12_data[self.width * self.height::2].reshape(
self.height // 2, self.width // 2)
shrunk_v = nv12_data[self.width * self.height + 1::2].reshape(
self.height // 2, self.width // 2)
u = cv2.resize(shrunk_u, (self.width, self.height),
interpolation=cv2.INTER_NEAREST)
v = cv2.resize(shrunk_v, (self.width, self.height),
interpolation=cv2.INTER_NEAREST)
yuv444 = np.dstack((y, u, v))
Also, I did a time comparison for processing 1000 pics. Turns out the cv reshape is quicker and guarantees the same result.
cv time: 4.417593002319336, pil time: 5.395732164382935
Update on 06/25/2021:
Pillow resize has different default resample param values in different versions.
5.1.0:
def resize(self, size, resample=NEAREST, box=None):
8.1.0:
def resize(self, size, resample=BICUBIC, box=None, reducing_gap=None):
It would be a good idea to specify the resample strategy used.
You may use the process described in my following post, in reverse order (without the RGB part).
Illustration:
Start by creating a synthetic sample image in NV12 format, using FFmpeg (command line tool).
The sample image is used for testing.
Executing from Python using subprocess module:
import subprocess as sp
import shlex
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=1 -vcodec rawvideo -pix_fmt nv12 nv12.yuv'))
sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x162 -pixel_format gray -i nv12.yuv -pix_fmt gray nv12_gray.png'))
Read the sample image, and executing the code from your post (used as reference):
import numpy as np
import cv2
nv12 = cv2.imread('nv12_gray.png', cv2.IMREAD_GRAYSCALE)
cols, rows = nv12.shape[1], nv12.shape[0]*2//3
# Reference implementation - using for-loops (the solution is in the part below):
################################################################################
nv12_y_data = nv12[0:rows, :].flatten()
nv12_u_data = nv12[rows:, 0::2].flatten()
nv12_v_data = nv12[rows:, 1::2].flatten()
yuv444_res = np.zeros((rows, cols, 3), np.uint8)
for h in range(rows):
# centralize yuv 444 data for inference framework
for w in range(cols):
yuv444_res[h][w][0] = (nv12_y_data[h * cols + w]).astype(np.int8)
yuv444_res[h][w][1] = (nv12_u_data[int(h / 2) * int(cols / 2) + int(w / 2)]).astype(np.int8)
yuv444_res[h][w][2] = (nv12_v_data[int(h / 2) * int(cols / 2) + int(w / 2)]).astype(np.int8)
################################################################################
My suggested solution applies the following stages:
Separate U and V into two "half size" matrices shrunk_u and shrunk_v.
Resize shrunk_u and shrunk_v to full image size matrices using cv2.resize.
In my code sample I used nearest neighbor interpolation for getting the same result as your result.
It is recommended to replace it with linear interpolation for better quality.
Use np.dstack for merging Y, U and V into YUV (3 color channels) image.
Here is the complete code sample:
import numpy as np
import subprocess as sp
import shlex
import cv2
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=1 -vcodec rawvideo -pix_fmt nv12 nv12.yuv'))
sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x162 -pixel_format gray -i nv12.yuv -pix_fmt gray nv12_gray.png'))
#sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x108 -pixel_format nv12 -i nv12.yuv -vcodec rawvideo -pix_fmt yuv444p yuv444.yuv'))
#sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x324 -pixel_format gray -i yuv444.yuv -pix_fmt gray yuv444_gray.png'))
#sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x108 -pixel_format yuv444p -i yuv444.yuv -pix_fmt rgb24 rgb.png'))
#sp.run(shlex.split('ffmpeg -y -f rawvideo -video_size 192x108 -pixel_format gbrp -i yuv444.yuv -filter_complex "extractplanes=g+b+r[g][b][r],[r][g][b]mergeplanes=0x001020:gbrp[v]" -map "[v]" -vcodec rawvideo -pix_fmt rgb24 yuvyuv.yuv'))
#sp.run(shlex.split('ffmpeg -y -f rawvideo -video#_size 576x108 -pixel_format gray -i yuvyuv.yuv -pix_fmt gray yuvyuv_gray.png'))
nv12 = cv2.imread('nv12_gray.png', cv2.IMREAD_GRAYSCALE)
cols, rows = nv12.shape[1], nv12.shape[0]*2//3
nv12_y_data = nv12[0:rows, :].flatten()
nv12_u_data = nv12[rows:, 0::2].flatten()
nv12_v_data = nv12[rows:, 1::2].flatten()
yuv444_res = np.zeros((rows, cols, 3), np.uint8)
for h in range(rows):
# centralize yuv 444 data for inference framework
for w in range(cols):
yuv444_res[h][w][0] = (nv12_y_data[h * cols + w]).astype(np.int8)
yuv444_res[h][w][1] = (nv12_u_data[int(h / 2) * int(cols / 2) + int(w / 2)]).astype(np.int8)
yuv444_res[h][w][2] = (nv12_v_data[int(h / 2) * int(cols / 2) + int(w / 2)]).astype(np.int8)
y = nv12[0:rows, :]
shrunk_u = nv12[rows:, 0::2].copy()
shrunk_v = nv12[rows:, 1::2].copy()
u = cv2.resize(shrunk_u, (cols, rows), interpolation=cv2.INTER_NEAREST) # Resize U channel (use NEAREST interpolation - fastest, but lowest quality).
v = cv2.resize(shrunk_v, (cols, rows), interpolation=cv2.INTER_NEAREST) # Resize V channel
yuv444 = np.dstack((y, u, v))
is_eqaul = np.all(yuv444 == yuv444_res)
print('is_eqaul = ' + str(is_eqaul)) # is_eqaul = True
# Convert to RGB for display
yvu = np.dstack((y, v, u)) # Use COLOR_YCrCb2BGR, because it's uses the corrected conversion coefficients.
rgb = cv2.cvtColor(yvu, cv2.COLOR_YCrCb2BGR)
# Show results:
cv2.imshow('nv12', nv12)
cv2.imshow('yuv444_res', yuv444_res)
cv2.imshow('yuv444', yuv444)
cv2.imshow('rgb', rgb)
cv2.waitKey()
cv2.destroyAllWindows()
Input (NV12 displayed as Grayscale):
Output (after converting to RGB):
Seems to be a prime case for fancy indexing (advanced indexing).
Something like this should do the trick, though I didn't verify it on an actual image. I've added a section to reconstruct the image in the beginning, because it is easier to work with the array as a whole than broken into parts. Likely, you can refactor this and avoid splitting it to begin with.
# reconstruct image array
y = nv12_y_data.reshape(self.image_shape[0], self.image_shape[1])
u = nv12_u_data.reshape(self.image_shape[0], self.image_shape[1])
v = nv12_v_data.reshape(self.image_shape[0], self.image_shape[1])
img = np.stack((y,u,v), axis=-1)
# take every index twice until half the range
idx_h = np.repeat(np.arange(img.shape[0] // 2), 2)[:, None]
idx_w = np.repeat(np.arange(img.shape[1] // 2), 2)[None, :]
# convert
yuv444 = np.empty_like(img, dtype=np.uint8)
yuv444[..., 0] = img[..., 0]
yuv444[..., 1] = img[idx_h, idx_w, 1]
yuv444[..., 2] = img[idx_h, idx_w, 2]
If this is along your critical path, and you want to tease out a little more performance, you could consider processing the image channel first, which will be faster on modern CPUs (but not GPUs).
This answer is just another way to do it, and is not the quickest way to get the job done, but definitely should be easy to understand. I have checked the generated files with yuvplayer application as well to confirm it works.
#height mentioned is height of nv12 file and so is the case with width
def convert_nv12toyuv444(filename= 'input.nv12',height=2358,width=2040):
nv12_data = np.fromfile(filename, dtype=np.uint8)
imageSize = (height, width)
npimg = nv12_data.reshape(imageSize)
y_height = npimg.shape[0] * (2/3)
y_wid = npimg.shape[1]
y_height = int(y_height)
y_wid = int(y_wid)
y_data= npimg[:y_height,:y_wid]
uv_data=npimg[y_height:,:y_wid]
shrunkU= uv_data[:, 0 : :2]
shrunkV= uv_data[:, 1 : :2]
u = cv2.resize(shrunkU, (y_wid, y_height),
interpolation=cv2.INTER_NEAREST)
v = cv2.resize(shrunkV, (y_wid, y_height),
interpolation=cv2.INTER_NEAREST)
yuv444 = np.dstack((y_data, u, v))
I am not able to get good color quality from using ImageMagick to convert PDF to images.
MagickReadSettings settings = new MagickReadSettings();
settings.Verbose = true;
settings.Density = new Density(600, 600);
MagickImageCollection images = new MagickImageCollection();
images.Read("C:\\" + Path.GetFileName(fileUrl));
List <string> files = new List<string>();
for (var x = 0; x < images.Count; x++)
{
images[x].Quality = 100;
images[x].BitDepth(24);
images[x].Contrast(true);
images[x].Resize(3675, 2400);
images[x].Write("C:\\websites\\FlyerEditor2\\FlyerEditor\\src\\assets\\" + Path.GetFileNameWithoutExtension(fileUrl) + "-" + (x + 1) + ".jpeg");
files.Add("assets/" + Path.GetFileNameWithoutExtension(fileUrl) + "-" + (x + 1) + ".jpeg");
}
cropped screenshot from pdf
jpg from pdf using imageMagick
if use python3, you can try use wand.
in terminal:
brew install imagemagick#6
pip install wand
in python:
from wand.image import Image
pdf_file = '.../example/a.pdf'
def convert_pdf_to_jpg(file_name, pic_file, resolution=120):
with Image(filename=file_name, resolution=resolution) as img:
print('pages = ', len(img.sequence))
with img.convert('jpeg') as converted:
converted.save(filename=pic_file)
I found major differences in imagemagick's convert handling of colorspace between Linux and Windows.
Using commands
convert -density 300 -colorspace RGB my.pdf my.jpg
convert -density 300 -colorspace sRGB my.pdf my.jpg
On Linux, both -colorspace sRGB and -colorspace RGB generated images where contrast and palette were a major diversion from the original, contrast was increased and colors were a far match from the original.
On Windows, both -colorspace sRGB and -colorspace RGB were acceptable if not perfect.
Ok the issue has nothing to do with imageMagick. It is a simple issue with color pallets. Converting a pdf to a jpeg by default uses cmyk, while the web standard is RGB
I'm trying to convert a pdf to png files per page and removing the 4th alpha channel. ImageMagick is behaving weirdly in that it is removing alpha correctly for all but one page. Is there an error in my command?
Here is the pdf: http://papers.nips.cc/paper/3723-anomaly-detection-with-score-functions-based-on-nearest-neighbor-graphs.pdf
Command I'm executing:
convert -units PixelsPerInch -density 300 -alpha remove nips09_4.pdf nips09_4.png
Result:
$ identify -verbose nips09_4-2.png
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 2480x3508+0+0
Resolution: 118.11x118.11
Print size: 20.9974x29.7011
Units: PixelsPerCentimeter
Type: TrueColorAlpha
Endianess: Undefined
Colorspace: sRGB
Depth: 16-bit
Channel depth:
red: 16-bit
green: 16-bit
blue: 16-bit
alpha: 1-bit
$ identify -verbose nips09_4-1.png
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 2480x3508+0+0
Resolution: 118.11x118.11
Print size: 20.9974x29.7011
Units: PixelsPerCentimeter
Type: Palette
Endianess: Undefined
Colorspace: sRGB
Depth: 16-bit
Channel depth:
red: 16-bit
green: 16-bit
blue: 16-bit
To reproduce:
cd ~/Downloads
wget http://papers.nips.cc/paper/3723-anomaly-detection-with-score-functions-based-on-nearest-neighbor-graphs.pdf
mv 3723-anomaly-detection-with-score-functions-based-on-nearest-neighbor-graphs.pdf nips09_4.pdf
convert -units PixelsPerInch -density 300 -alpha remove nips09_4.pdf nips09_4.png
Try using -alpha off instead, after loading the PDF, and see if that helps. Like this:
convert -density 300 some.pdf -alpha off nips%03d.png
I believe -alpha remove will remove the effect of the alpha channel but actually leave it still present, but opaque, in the image and that gets transferred onwards to your PNG images.
In contrast, alpha off actually removes the channel altogether and so it doesn't show up in the PNG images.