PHP convert 12digit hex to 6 - php

I am parsing a XML file supplied by some software. Part of the parsing is extracting colors from some attributes. The problem I have is the color is a 12digit hex value. ie,
<Text AdornmentStyle="0" Background="#FFFFFFFFFFFF" Color="#DD6B08C206A2" Font="Courier Final Draft" RevisionID="0" Size="12" Style="">Test</Text>
As you can see the colors are 12digits long. I need to get the 6 digit color so I can display it correctly on html.
Has anyone come across this before?
Hope you can advise.

Never seen a 12-digit hex color string before. Must be using 2-bytes per channel, which means if you convert it, you're going to lose a bit of information.
I believe the color is in the format #RRRRGGGGBBBB, so take each 4 hexgits and divide by (16^4/16^2)=256, and round if necessary. That should do it.
...and if that doesn't give you the right color, try CMYK like cypher suggests: #CCCMMMYYYKKK (12-bits per channel).
e.g., to convert DD6B08C206A2 do:
0xDD6B / 0x100 = 0xDD
0x08C2 / 0x100 = 0x08
0x06A2 / 0x100 = 0x06
Put those back together and you get #DD0806.

Related

calculate SVG path length in PHP like getTotalLength() in JS

I'm trying to modify SVG files via a PHP script and at one point I need to calculate the length of some path elements.
In JavaScript, there's the handy function .getTotalLength(), but I wasn't able to find a PHP parser for SVG that offers something similiar, so I guess I'll have to manually parse the d-attribute and calculate the paths.
Loading the XML, getting the attribute etc. is not the problem, but I'm not very good at mathematics and especially not in the field of vectors. Let's take this example:
<path d="m 268.87448,476.05362 c -25.0135,11.49888 -35.53725,21.39636 -29.14819,47.61221 -0.79153,89.53821 7.5531,195.5936 -11.71546,284.63588 -24.02796,67.23588 -51.61983,89.1027 -112.32477,124.52935 0,0 -38.977804,16.40902 -54.19931,20.52688" />
What I would do first is explode the path by spaces and iterate through the result, then check whether it's a letter or a number and act accordingly. And that's where I'm stuck and don't even know how to begin.
I have read the SVG path specs at https://www.w3.org/TR/SVG/paths.html - but still can't get my mind around the number crunching.

Creating a code128 barcode in PHP, using a font instead of rendering it as an image

I need to be able to convert any string into a code128 barcode that can be printed on a PDF.
My idea was to embed a code128 font into the PDF and simply use that font to render the string that I need to show as a barcode, letter for letter.
However, I found out that I also need to calculate a checksum and include the start and stop characters.
Is this not possible using PHP? I have not found any solution anywhere. The only solutions that I could find are for directly rendering the barcode as an image, which does not help in my current situation, since I need to use a font to create the barcode in the PDF.
If you restrict your efforts to 128B, you have access to upper and lower case characters, numbers and most punctuation. It also saves you from having to write code to shift in and out of A and C symbologies. This makes the code to calculate the checksum really trivial.
Code 128B start character has a value of 104. The stop character for all Code 128 variations has a value of 106, but that value does not figure into the chksum calculation. Let's pick the string "Hello" for a real life exercise. You'll want to make sure you have access to the Code 128 table. All the values I will be discussing are out of that table and not ASCII or UTF-8.
The checksum is calculated by adding the multiple of a character’s value by its position in the barcode with the exception of the start code.
While the start code’s position is ‘1’, so is the position of the first character following the start code. So the start code and the first byte of data (‘H’) are both multiplied by the number 1 ((104 × 1) + (40 × 1) = 144).
The following 4 bytes get an incrementally higher multiplier ((69 x 2) + (76 × 3) + (76 × 4) + (79 × 5) = 1065). Summing it all up together (144 + 1065) we get 1209.
You should be able to use the modulus operator (1209 % 103) in PHP to get 76 for the checksum character for the Code 128B string “Hello” (the 103 is a constant, trust me on that). So the final array of codes to map "Hello" into a Code 128 barcode is:
[104 40 69 76 76 79 76 106].
You'll need lookup tables to convert the string character values to Code 128B character values to whatever your barcode font is expecting. But all you need is a loop, an array index, an accumulator for the sum of the factors and a modulus operator against the constant value of 103.
The easisest way to generate a barcode in PHP for PDF is to use a dedicated software library.
AFAIK, the most complete one is currently the tc-lib-barcode (https://github.com/tecnickcom/tc-lib-barcode) that allows you to generate both linear and bidimensional barcodes. The included example should give you a quick start.
The source code is fully PSR-2 compliant and can be easily added to your PHP projects using Composer.
The original code has been ported and refactored from TCPDF and already used in billions of documents.

Encoding unique IDs to a maximum document size of 100kb

This is going to be a nice little brainbender I think. It is a real life problem, and I am stuck trying to figure out how to implement it. I don't expect it to be a problem for years, and at that point it will be one of those "nice problems to have".
So, I have documents in my search engine index. The documents can have a number of fields, however, each field size must be limited to only 100kb.
I would like to store the IDs, of particular sites which have access to this document. The site id count is low, so it is never going to get up into the extremely high numbers.
So example, this document here can be accessed by sites which have an ID of 7 and 10.
Document: {
docId: "1239"
text: "Some Cool Document",
access: "7 10"
}
Now, because the "access" field is limited to 100kb, that means that if you were to take consecutive IDs, only 18917 unique IDs could be stored.
Reference:
http://codepad.viper-7.com/Qn4N0K
<?php
$ids = range(1,18917);
$ids = implode(" ", $ids);
echo mb_strlen($ids, '8bit') / 1024 . "kb";
?>
// Output
99.9951171875kb
In my application, a particular site, of site ID 7, tries to search, and he will have access to that "Some Cool Document"
So now, my question would be, is there any way, that I could some how fit more IDs into that field?
I've thought about proper encoding, and applying something like a Huffman Tree, but seeing as each document has different IDs, it would be impossible to apply a single encoding set to every document.
Prehaps, I could use something like tokenized roman numerals?
Anyway, I'm open to ideas.
I should add, that I want to keep all IDs in the same field, for as long as possible. Searching over a second field, will have a considerable performance hit. So I will only switch to using a second access2 field, when I have milked the access field for as long as possible.
Edit:
Convert to Hex
<?php
function hexify(&$item){
$item = dechex($item);
}
$ids = range(1,21353);
array_walk( $ids, "hexify");
$ids = implode(" ", $ids);
echo mb_strlen($ids, '8bit') / 1024 . "kb";
?>
This yields a performance boost of 21353 consecutive IDs.
So that is up like 12.8%
Important Caveat
I think the fact that my fields can only store UTF encoded characters makes it next to impossible to get anything more out of it.
Where did 18917 come from? 100kb is a big number.
You have 100,000 or so bytes. Each byte can be 255 long, if you store it as a number.
If you encode as hex, you'll get 100,000 ^ 16, which is a very large number, and that just hex encoding.
What about base64? You stuff 3 bytes into a 4 byte space (a little loss), but you get 64 characters per character. So 100,000 ^ 64. That's a big number.
You won't have any problems. Just do a simple hex encoding.
EDIT:
TL;DR
Let's say you use base64. You could fit 6.4 times more data in the same spot. No compression needed.
How about using data compression?
$ids = range(1,18917);
$ids = implode(" ", $ids);
$ids = gzencode($ids);
echo mb_strlen($ids, '8bit') / 1024 . "kb"; // 41.435546875kb

Converting a PDF to JPG with ImageMagick in PHP Gives Odd Letter Spacing

I am trying to convert a PDF to a JPG with a PHP exec() call, which looks like this:
convert page.pdf -resize 716x716 page.jpg
For some reason, the JPG comes out with janky text, despite the PDF looking just fine in Acrobat and Mac Preview. Here is the original PDF:
http://whit.info/dev/conversion/page.pdf
and here is the janktastic output:
http://whit.info/dev/conversion/page.jpg
The server is a LAMP stack with PHP 5 and ImageMagick 6.2.8.
Can you help this stumped Geek?
Thanks in advance,
Whit
ImageMagick is just going to call out to Ghostscript to convert this PDF to an image. If you run gs on the pdf, you get the same badly-spaced output.
I suspect Ghostscript isn't handling the PDF's embedded TrueType fonts very well. If you could change your output to either embed Type 1 fonts or use a "core" PostScript font, you'd get better results.
I suspect its an encoding/widths issue. Both are a tad off, though I can't put my finger on why.
Here are some suspects:
First
The text stream is defined in UTF-16 LE. charNULLcharNULL, using the normal string drawing command syntax:
(some text) Tj
There's a way to escape any old character value into a () string. You can also define strings in hex thusly:
<203245> Tj
Neither method are used, just the questionable inline nulls. That could cause an issue in GS if it's trying to work with pointers to char without lengths associated with them.
Second
The widths array is dumb. You can define widths in groups thusly:
[ 32 [450 525 500] 37 [600 250] 40 [0] ]
This defines
32: 450
33: 525
34: 500
37: 600
38: 250
40: 0
These fonts defines their consecutive widths in individual arrays. Not illegal, but definitely wasteful/stupid, and if GS were coded to EXPECT gaps between the arrays, it could induce a bug.
There's also some extremely fishy values in the array. 32 through 126 are defined consecutively, but then it starts jumping all over: ...126 [600] 8364 [500] 8216 [222] 402 [500] 8222 [389]. 8230 [1000] 8224 [444]... and then goes back to being consecutive from 160 to 255.
Just weird.
Third
I'm not even remotely sure, but the CIDToGIDMap stream contains an AWEFUL lot of nulls.
Bottom line
Those fonts are fishy. And I've never heard of "Bellflower Books" or "UFPDF 0.1"
That version number makes me cringe. It should make you cringe too.
Googleing for "UFPDF" I found this note from the author:
Note: I wrote UFPDF as an experiment, not as a finished product. If you have problems using it, don't bug me for support. Patches are welcome though, but I don't have much time to maintain this.
UFPDF is a PHP library that sits on top of FPDF. 0.1. Just run away.

How to check a PNG for grayscale/alpha color type?

PHP and GD seem to have trouble creating images from PNGs of type greyscale with alpha when using imagecreatefrompng(). The results are incredibly distorted.
I was wondering if anyone knew of a way to test for the colour type in order to notify the user of the incompatibility?
Example:
Original Image: http://dl.dropbox.com/u/246391/Robin.png
Resulting Image: http://dl.dropbox.com/u/246391/Robin_result.png
Code:
<?php
$resource = imagecreatefrompng('./Robin.png');
header('Content-type: image/png');
imagepng($resource);
imagedestroy($resource);
Cheers,
Aron
The colour type of a PNG image is stored at byte offset 25 in the file (counting from 0). So if you can get hold of the actual bytes of the PNG file, simply look at byte 25 (I don't do PHP, so I don't know how to do that):
0 - greyscale
2 - RGB
3 - RGB with palette
4 - greyscale + alpha
6 - RGB + alpha
The preceding byte (offset 24) gives the number of bits per channel. See the PNG spec for more details.
In a slight twist a PNG file may have "1-bit alpha" (like GIFs) by having a tRNS chunk (when it is colour type 0 2 or 3).
i landed here today searching for a way to tell (via php) if a specific .png image is an alpha-png one -
David Jones' answer points to the right direction, really easy to implement in php:
file_get_contents to load just that 25' byte (there it is, indeed!), and
ord() to get its ASCII value, to test it (against '6' in my case)
if(ord(file_get_contents($alpha_png_candidate, NULL, NULL, 25, 1)) == 6) {
is_alpha_png_so_do_something();
}
actually i needed that for assuring backward compatibility with ie6
within cms-user-generated-pages, to replace all alpha-png < img > tags with inline-block < spans > - the alpha-png file will then be served as variable for the ms-proprietary css property filter
.alpha_png_span{
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='$alpha_png_candidate', sizingMethod='crop')
}
...and it all works, so thanks!
paolo
see this answer
:
Another usefull note for those using ImageCreateFromPng:
PHP and GD do not recognize grayscale/alpha images.
So if you use grayscale images with transparency between 0% and 100%, then save the image as RGB.
At least this is true for PHP Version 4.4.2-1 and in 5.1.2-1 with pictures made with GIMP 2.2.8.
url :
http://php.net/manual/en/function.imagecreatefrompng.php

Categories