I use package pdf-to-image for Yii2 based on Imagick library to convert each page of PDF to image. Also I need to get width and height or format of particular PDF page. Is there any way to do that?
Imagick is a native php extension to create and modify images using the ImageMagick API. So doesn't retry any PDF's info but image's info:
Imagick::getNumberImages — Returns the number of images in the
object.
$pdf->getNumberOfPages(); //returns number of images that are equal to number of PDF's pages. This is a method from pdf-to-image package.
A PDF describes the content and appearance of one or more pages. It also contains a definition of the physical size of those pages. That page size definition is not as straightforward as you might think. There can in fact be up to 5 different definitions in a PDF that relate to the size of its pages. These are called the boundary boxes or page boxes.
The MediaBox is used to specify the width and height of the page. For the average user, this probably equals the actual page size.
Each page in a PDF can have different sizes for the various page boxes.
A PDF always has a MediaBox definition. All the other page boxes do not necessarily have to be present in regular PDF files.
The MediaBox is the largest page box in a PDF. The other page boxes can equal the size of the MediaBox but they are not expected to be larger (The latter is explicitly required in the PDF/X-4 requirements). If they are larger, the PDF viewer will use the values of the MediaBox.
You should be able to retrieve the exact "HiResBoundingBox" value (which is the MediaBox value in PDF).
A test document is A4 (210mm x 297mm) which is 595.28pt x 841.89pt and has four(4) pages.
The unit of these values is PostScript points (where 72 pt == 1 inch).
$pdf = "1.pdf";
$output = shell_exec("identify -format \"%[pdf:HiResBoundingBox]\" $pdf");
echo $output;
prints this String:
595.28x841.89+0+0595.28x841.89+0+0595.28x841.89+0+0595.28x841.89+0+0
with some REGEX you could get width:595.28pt and height:841.89pt for each page and convert them to millimeters.
How about this approach?
By Imagick I can easily get image from pdf file
$RESOLUTION = 300;
$myurl = 'filename.pdf['.$pagenumber.'];'
$image = new Imagick($myurl);
$image->setResolution( $RESOLUTION , $RESOLUTION );
$image->setImageFormat( "png" );
$image->writeImage('newfilename.png');
Now I have image from page of PDF file. I know resolution (number pixels per inch) and I can get width and height of image in pixels. So don't need to have deep knowledge in math to calculate width and height of page of PDF in inch:
$pdfPageWidth = $imageWidth / $RESOLUTION;
$pdfPageHeight = $imageHeght/ $RESOLUTION;
Related
I am getting a .gif image back from the UPS API that I need to build an 8.5x11 pdf image out of (for printing). I can build a PDF, but it's huge - more like 11x8.5. How can I shrink the width of the output document? The resizeImage call didn't seem to do it.
$base64_string = $accept->PackageResults->LabelImage->GraphicImage;
$imageBlob = base64_decode( $base64_string);
$img = new Imagick();
$img->readImageBlob($imageBlob);
$img->setImageFormat('pdf');
$img->setImagePage(612,792); // Letter size
$success = $img->writeImage($label_file);
It seems like I can reduce the size with
$img->setResolution(216, 216);
but then the smaller image appears in the upper left hand edge of the page, which still makes it unusable. How could I center the image on the page or at least create a 2" left margin?
Is something like
$img->borderImage('white', <some_number>, 0);
the way to go? (The use case here is that people want to send this image directly to their label printer.)
I need to generate jpg images from PDF files (first page only). The PDF files are user generated, so they can contain anything. I'm currently using the following code:
// Load PDF.
$i = new Imagick;
// Create thumbnail of first page of PDF.
$i->setResolution(150, 150);
$i->loadImage("test.pdf[0]");
$i->thumbnailImage(640, 480, true);
// Remove transparency, fill transparent areas with white rather than black.
$i->setImageBackgroundColor("white");
$i->setImageAlphaChannel(11); // Imagick::ALPHACHANNEL_REMOVE
$i->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
// Output.
$i->writeImage("test.jpg");
This works as expected in that transparency becomes white instead of black. However, I've run into problems with some generated jpg images, so I ran jpeginfo on them:
$ jpeginfo -c test.jpg
test.jpg 960 x 480 32bit JFIF N 9481 Unsupported color conversion request [ERROR]
It turns out that some source PDFs actually use CMYK, and apparently are not converted to RGB when saved as jpg. So I changed my code to the following (addition of a single line) to explicitly convert to RGB:
// Load PDF.
$i = new Imagick;
// Create thumbnail of first page of PDF.
$i->setResolution(150, 150);
$i->loadImage("test.pdf[0]");
$i->thumbnailImage(640, 480, true);
// Remove transparency, fill transparent areas with white rather than black.
$i->setImageBackgroundColor("white");
$i->setImageAlphaChannel(11); // Imagick::ALPHACHANNEL_REMOVE
$i->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
// Convert to RGB to prevent creating a jpg with CMYK colors.
$i->setImageColorspace(Imagick::COLORSPACE_RGB);
// Output.
$i->writeImage("test.jpg");
This creates a jpeg with an RGB color profile, all right. However, for some obscure reason it results in an image with a black background again. In other words: the transparency problem is back. Why does Imagick do this, and more importantly, what's the solution to both the transparency problem and the CMYK problem?
The correct function to use is transformImageColorspace not setImageColorspace. transformImageColorspace is used for existing images, setImageColorspace is for new images e.g. svg drawing..
I've added it to the manual and it should show up soon.
I'm trying to downsample every image that I consider large for my site on uploading, so when a user tries to upload an image I firstly check if it has an acceptable resolution, otherwise I want to drop this resolution. The code I use for this is:
if ($image->isValid()){
$imagick = new \Imagick();
$imagick->readImage($image);
$resolution = $imagick->getImageResolution();
$resolution_x = $resolution['x'];
$resolution_y = $resolution['y'];
if ($resolution_x > 30 && $resolution_y > 30){
$imagick->setImageResolution($resolution_x,$resolution_x);
$imagick->resampleImage($resolution_x/2,$resolution_x/2,\imagick::FILTER_CATROM,1);
}
$imagick->writeImage($uploadDir.$path);
}
This code was supposed to set the resolution of an image with resolution 300 dpi for example to 150dpi. Instead of this, the resolution remains 300 dpi and the image dimensions drop to the half of their previous values (e.g an image (1200x800) turns into (600x400)). Am I missing something about the functionality of Imagick::resampleImage or is there any error in my code? I've done a lot of search before post this question and tried lot of different ways to succeed my goal using Imagick but I cannot get it done!
The 'resolution' in the setImageResolution and getImageResolution functions refer to the dots per inch setting of the image, which is a hint to printers of what size to print the image i.e. how many dots per inch it should be printed at.
It does not affect the pixel dimensions of the image, and so does not have a noticeable effect on the image on a computer, which does not use the DPI setting to render an image.
You want to use either just $imagick->getImageWidth() and $imagick->getImageHeight() or $imagick->getImageGeometry() to get the pixel size of the image, and then resample it based on those pixel dimension, rather than the printer hint setting.
It sounds like the resolution values should be the same in both setImageResolution and resampleImage. Have you tried this yet?
$imagick->setImageResolution($resolution_x/2,$resolution_x/2);
I'm trying to find the fastest way to convert a multiple pdf in to jpeg images without quality loss. I have the following code:
$this->imagick = new \Imagick();
$this->imagick->setresolution(300,300);
$this->imagick->readimage($this->uploadPath . '/original/test.pdf');
$num_pages = $this->imagick->getNumberImages();
for($i = 0;$i < $num_pages; $i++) {
$this->imagick->setIteratorIndex($i);
$this->imagick->setImageFormat('jpeg');
$this->imagick->readimage($asset);
// i need the width, height and filename of each image to add
// to the DB
$origWidth = $this->imagick->getImageWidth();
$origHeight = $this->imagick->getImageHeight();
$filename = $this->imagick->getImageFilename();
$this->imagick->writeImage($this->uploadPath . '/large/preview-' . $this->imagick->getIteratorIndex() . '.jpg');
$this->imagick->scaleImage($origWidth / 2, $origHeight / 2);
$this->imagick->writeImage($this->uploadPath . '/normal/preview-' . $this->imagick->getIteratorIndex() . '.jpg');
//add asset to the DB with the given width, height and filename ...
}
This is very slow thou, partially because the resolution is so big but is i dont add it, the text on the images is of very poor quality. Also, the fact that i'm saving the image first, and then also saving a smaller version of the file is probably not very optimized.
So does anyone have a better method of doing this? Maybe with only ghostscript?
The minimum requirements are that i need 2 versions of the converted image. A real size version and a version at half size. And i need the width and height and filename to add to the database.
You can use Ghostscript, if you set "-sDEVICE=jpeg -sOutputFile=out%d.jpg" then each page will be written to a separate file.
Note that its not really possible to render a PDF to JPEG 'without quality loss' since JPEG is a lossy compression method. Have you considered using a lossless format instead, such as PNG or TIFF ?
To get the same images at different sizes you will need to render the file twice at different resolutions, you set resolution in Ghostscript with '-r'. The width and height can be read easily enough from the image file, or you can use pdf_info.ps to get each page size. Note that a PDF file can contain multiple pages of different sizes, I hope you aren't expecting them all to be the same....
I am making an avatar script from scratch and am having some problems. I got transparency working, and multi-image support for heads, bodies, shirts, etc.
Anyhow, I want to be able to generate specific sizes of the avatar within the PHP script. At this time, I have the variable $baseImage, which is an image generated using the GD script below:
$baseImage = imagecreatefrompng($startAsset);
imagealphablending($baseImage, true);
imagesavealpha($baseImage, true);
... combine all images into $base here
header("Content-type: image/png");
imagepng($baseImage);
The size of the image this generates is 350x550 (pixels) and I want to be able to get a smaller size.
I've done research but cannot find a working solution. What built-in PHP GD functions can resize this, retain transparency, and keep the great quality/colors?
There is no way to change the size of an image resource directly. Instead, you need to create a new image of the desired size and use imagecopyresampled to copy from the fullsize image to the resized one.