phpdocx add image makes docx corrupt - php

It has been asked before, years ago, but with no answer corrupt docx when adding image
Hey
I have a template where i replace some variables and generate a docx document... That works fine..
As soon as i add an image, word tells me that the files is corrupt. But letting Word correct the error gives me the document as i expect it to be with the image.
Im adding image like this...
$docx->addBreak(array('type' => 'page'));
$options = array(
'src' => $value['110333870356bc784cf1b6b0.56722572.png'],
'imageAlign' => 'center',
'scaling' => 100,
'spacingTop' => 10,
'spacingBottom' => 0,
'spacingLeft' => 0,
'spacingRight' => 20,
'textWrap' => 0,
);
$docx->addImage($options);
Im lost here .. ? ..

After being in contact with 2mdc (Creator of phpDocX) they told me, that PHP is not able to get the right extension because of the filename of the image i am inserting. As a result phpDocX adds some wrong values (such as dpi and image extension name).
As mentioned in my question, Word is able to detect those errors and correct them.
Changed my routine which creates my "unique" image names, to make sure that dot's are not present and it fixed the problem ..
As a result, filename: 110333870356bc784cf1b6b0.56722572.png will instead become 110333870356bc784cf1b6b0656722572.png (or other generated filename).

Just to share my experience.
I had exactly the same problem but not for the same reason.
It was because the image file extension I wanted to insert (addImage) was in capital letter.
Example :
image.JPG ==> result a "corrupt" file.
image.jpg ==> result OK !
I hope it will help someone...

Related

ImageMagick with PHP text overflowing PDF to JPG conversion

I'm trying now to convert a PDF file to JPG, using ImageMagick with PHP and CakePHP. The PDF is in perfect shape and it's right the way it should be, but the image generated from the PDF is always overflowing the borders of the file.
Until now, I've tried tweaking the code for the generation with no sucess, reading a lot from the PHP docs (http://php.net/manual/pt_BR/book.imagick.php).
Here are the convertion code:
$image = new Imagick();
$image->setResolution(300,300);
$image->setBackgroundColor('white');
$image->readImage($workfile);
$image->setGravity(Imagick::GRAVITY_CENTER);
$image->setOption('pdf:fit-to-page',true);
$image->setImageFormat('jpeg');
$image->setImageCompression(imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(60);
$image->scaleImage(1200,1200, true);
$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
$image->writeImage(WWW_ROOT . 'files' . DS . 'Snapshots' . DS . $filename);
Here are the results:
https://imgur.com/a/ISBmDMv
The first image is the PDF before the conversion and the second one, the image generated from the PDF where the right side text overflows.
So, why this is happening? And if someone got some alternative for any tech used (the GhostScript, ImageMagick, etc) is also welcome!
Thanks everyone!
Its very hard to say why you see the result you do, without seeing the original PDF file, rather than a picture of it.
The most likely explanation is that your original PDF file uses a font, but does not embed that font in the PDF. When Ghostscript comes to render it to an image it must then substitute 'something' in place of the missing font. If the metrics (eg spacing) of the substituted font do not match precisely the metrics of the missing font, then the rendered text will be misplaced/incorrectly sized. Of course since its not using the same font it also won't match the shapes of the characters either.
This can result in several different kinds of problems, but what you show is pretty typical of one such class of problem. Although you haven't mentioned it, I can also see several places in the document where text overwrites as well, which is another symptom of exactly the same problem.
If this is the case then the Ghostscript back channel transcript will have told you that it was unable to find a font and is substituting a named font for the missing one. I can't tell you if Imagemagick stores that anywhere, my guess would be it doesn't. However you can copy the command line from the ImagMagick profile.xml file and then use that to run Ghostscript yourself, and then you will be able to see if that's what is happening.
If this is what is happening then you must either;
Create your PDF file with the fonts embedded (this is good practice anyway)
Supply Ghostscript with a copy of the missing font as a substitute
Live with the text as it is

Part of EXIF data read by exif_read_data() is corrupted

When I read the EXIF data from a raw file with exif_read_data() a lot of the data gets corrupted. Or so I think.
The file I'm trying to read is a DNG Raw file from a Pentax K-x camera.
Here is a demo: http://server.patrikelfstrom.se/exif/?file=_IGP6211.DNG
(I've added a standard JPEG from a Canon EOS 1000D as comparison)
I get no errors on this site and it seems to include data that exif_read_data() doesn't return.
http://regex.info/exif.cgi
And the corrupt data I'm talking about is: ...”¯/ѳf/ÇZ/íÔ.ƒ.9:./<ñ.TÛ¨.zâh!o†!™˜...
And: UndefinedTag:0xC65A
The server is running PHP version 5.5.3
Just because the data isn't human readable doesn't mean it's garbage.
Those values that you're seeing are private EXIF fields which are left up to the implementer to determine. They could be binary data, they could be text, they could be anything. This listing can help you determine what some of those values are.
For example, tag 0xC634 is DNGPrivateData which is data specifically for programs that deal with DNG files.
You can map the undefined tags to what they most likely are using this file:
https://github.com/peterhudec/image-metadata-cruncher/blob/master/includes/exif-mapping.php
It looks like your script is dying on 0xc634 => 'SR2Private'
Looking here http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html it looks like it is used to store information about the flash on the camera? I don't know for sure, but it probably is not imporant information, and probably not meant to be viewed in text format.
I would probably just make a list of what keys it seems to die on, loop through the exif data, see if it starts with undefinedkey: and either rename the key to the mapped one, or unset those items:
$bad_keys = array('0xc634', ..., '0xc723');
foreach ( $exif as $key => $value ) {
if ( strtolower( substr( $key, 0, 13 ) ) == 'undefinedtag:' ) {
//use the file with the map of undefined tags
//either change the key, or unset it if it's one
//that seems to be corrupt
}
}

Imagemagick resizing control quality and extension

I am trying to learn Imagemagick, php.net docs are terrible T_T, and I cannot seem to find any answers to my questions. I am wanting to allow people to upload images then resize them and lose EXIF data.
Heres what I have currently.
$thumbnail = new Imagick("http://4.bp.blogspot.com/-hsypkqxCH6g/UGHEHIH43sI/AAAAAAAADGE/0JBu9izewQs/s1600/luna-llena1.jpg");
$thumbnail->thumbnailImage( 100, 100, true );
$thumbnail->writeImage( "avatar/thumbnail.jpg" );
Now how do I control the image file that it is being saved as? Lets say the user submits a gif/png/jpg how would I go about taking that image then saving it as the same input format or changing them all to .png?
This IMO produces the best results for imagick thumbnails;
Load the picture
$img = new imagick( $_FILES['Picture']['tmp_name'] );
Trim an excess off the picture
$img->trimImage(0);
Create the thumbnail, in this case, I'm using 'cropThumbnailImage'
$img->cropThumbnailImage( 180, 180 );
Set the format so all pics can now be the same standard format
$img->setImageFormat( 'jpeg' );
Set the Image compression to that of a jpg
$img->setImageCompression(Imagick::COMPRESSION_JPEG);
Set the quality to be 100
$img->setImageCompressionQuality(100);
The resulting thumbnail is then a little bit blury IMO, so I add a slight sharpening effect to make it 'sharper'. . play around with these settings, but I like..
$img->unsharpMaskImage(0.5 , 1 , 1 , 0.05);
I agree, the PHP.net docs are not very helpful. I've found that it's easiest to find how to do things using commands, then match the commands up with the PHP methods. I'm a little late replying so you might have figured it out by now, but if not, or for the benefit of anyone else:
If you want to change the image format before saving, add this before your writeImage line:
$thumbnail->setImageFormat('png');
Then change the extension in your writeImage line to match, e.g. thumbnail.png
To change the quality, write:
$thumbnail->setImageCompressionQuality(40); // Adjust the number 40
In some cases you might also want to set the compression type by writing:
$thumbnail->setImageCompression(Imagick::COMPRESSION_JPEG);
You can find the COMPRESSION constants here: http://www.php.net/manual/en/imagick.constants.php
Note: These are just examples. This compression would not actually work with a png file.

How to generate a nice PDF with php Excel?

I'm using the last PHPExcel version (7.7 i think). I'm able to generate my excel. I have to generate the pdf version with tcpdf, no choice here.
But the result is ugly and oversized.
See the gigantic font-size for 2012-000012, is 11 in excel.
As you can see, there is 2 problems here. The document is oversized, and the borders are crappy.
In order to get rid of the oversized side, i tryied this :
$this->printer->getActiveSheet()->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);
And this :
$this->printer->getActiveSheet()->getPageSetup()->setScale(50);
The scale is set to 50, but it do not affect output. So how can i get rid of these 2 problems ?
Here is a screen, of my excel How to set auto-line break PhpExcel? .
UPDATE :
By setting cellspacing to 0 borders are handled almost as expected, still a sligth problem, maybe caused by the oversized problem.
See :
Is there an opion or a method call to set it to 0 ?
This lies in the writer\html.php line 915, since i don't display gridlines.
To remove the borders that you find objectionable turn off grid lines on each sheet that you want to render in your the pdf.
For example:
$objPHPExcel->getActiveSheet()->->setShowGridlines(false);
to solve this problem I do two operations.
Step one is to set orientation for PHPexcel object
$objPHPExcel->getActiveSheet()->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE);
Step two - set different paper size for PHPExcel object:
$objPHPExcel->getActiveSheet()->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER);
Then convert PHPExcel object to object writer
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'PDF');
$objWriter->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE);
$objWriter->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER);
This works for me. Also i changed font size inside PHPExcel object - just like this for headers
$objPHPExcel->setActiveSheetIndex($lastsheet)->getStyle("A1:K3")->applyFromArray(
array(
'font' => array(
'size' => 8
)
)
);
and for the rest of data:
$objPHPExcel->getDefaultStyle()->getFont()->setName('Arial')->setSize(8);
Now im trying to get of ugly borders that tcPDF generates and one additional row at the end of file...

Automatically create a json file which lists all images in a directory?

I have a directory "files" on my webspace. In this directory are png-images, which may change frequently.
The filenames need to be stored in a json file.
Is there a way to automatically create a json file which lists all images in a directory in the following way:
art_showWindow({"art":[
{"href":"http://www.domain.example/files/art_noveau_1.png","title":"Art Noveau 1"},
{"href":"http://www.domain.example/files/art_noveau_5.png","title":"Art Noveau 5"},
{"href":"http://www.domain.example/files/art_noveau_23.png","title":"Art Noveau 23"},
]});
The title can of course just be a repetition of the filename if the above is too difficult.
Is this somehow possible?
Thanks in advance for your help.
Thomas
As far as I know, there is not a magical native PHP function that does exactly that, although it would not be terribly surprising.
Since writing the script for you is not going to help you learn things much, I think it's best to point out a number of tools to use for this challenge.
First of all, you want to find all the PNG files in a directory; To list all the files (and directories) in a directory, use scandir($directory). From there on, you can use a foreach loop to iterate over the returned array, and only stick the PNG files in a new array.
Since the output of scandir does not make files and directories discernible, you might want to run is_dir on the results to make sure you only get the files.
You can then use pathinfo to retrieve the extension and base name (filename without its extension, labeled 'filename' in the output of pathinfo) of a current file. You will need the extension to figure out whether the file is a PNG (and thus one to add to your new array).
Once you've iterated over the scandir array and have created an array with PNG file names, you can start building your final array. You'll want to start another foreach loop, in which you prepend 'http://www.domain.example/files/' to the file names, and do some magic to convert the file name to a title. You want to array to be structured like this:
$art = array(
array(
'href' => $full_url,
'title' => $title
),
array(
'href' => $full_url,
'title' => $title
),
// etc
);
To get the title, I'd go with this seemingly complex one-liner:
$title = ucwords( // Give words an upper case first letter
str_replace('_', ' ', //replace underscores by spaces
substr($filename, 0, (strlen($filename) - 4) //strip .png extension
)
);
Once the foreach loop is done, you'll have a fully populate art array. To convert this to JSON, you simple use json_encode, like so:
$output = json_encode(array('art' => $art));
You mention you want to save it as a json file; Are you sure you don't just want PHP to output the JSON?
Either way, to save the file, easy enough, file_put_contents will do the job.
If you just want PHP to output it, you'll want to set the Content-Type HTTP header to application/json: header('Content-Type: application/json'); and then simply echo the $output.
Hope that helps!
(And I realise that this took more effort than just writing you a snippet of code, but at least you'll still have to do a little think work to accomplish it. Good luck!

Categories