I'm working on a project that involves talking directly with Zebra printers. Currently, I am trying to convert images to the GRF format using something called "ztools". ZTools appears to be ancient and doesn't always convert the graphic correctly.
I've began digging up information on the PCX file format it is converting from and now find myself in byte land. This is my reference at this time: PCX Technical Reference
So, I have a basic PCX file I saved from photoshop that is 2x2 and would look like this:
10
01
This is where I am stuck, however. I've never worked with bytes and am attempting to read the pcx file with PHP using fopen("file", "rb"); and fread. However, it seems no matter what I do, I get a bunch of zeros. Anyone know what I need to do to convert the bytes to there numeric equivalents?
This is my weak attempt:
<?php
$file = "test.pcx";
// Open the file for binary reading (b flag)
$handle = fopen($file, "rb");
while (!feof($handle)) {
$contents = fread($handle, 1);
$contents = $contents >> 8;
echo $contents >> 8;
$content .= $contents;
}
fclose($handle);
I was able to get the header information accurately with this:
<?php
$file = "test.pcx";
function intToBits($int) {
$return = "00000000";
if ($int <= 255 && $int >= 0) {
$check = 128;
$x = 0;
while ($int > 0) {
if ($int > $check) {
$return[$x] = "1";
}
$int -= $check;
$check /= 2;
$x++;
}
}
return $return;
}
// Open the file for binary reading (b flag)
$handle = fopen($file, "rb");
$PCX_MAP = array();
$PCX_MAP['Manufacturer'][0] = 1; // Manufacturer
$PCX_MAP['Version'] = 1; // Version Info
$PCX_MAP['Encoding'] = 1; // Encoding
$PCX_MAP['BitsPerPixel'] = 1; // BitsPerPixel
$PCX_MAP['Xmin'] = 2; // Window Xmin
$PCX_MAP['Ymin'] = 2; // Window Ymin
$PCX_MAP['Xmax'] = 2; // Window Xmax
$PCX_MAP['Ymax'] = 2; // Window Ymax
$PCX_MAP['HDpi'] = 2; // HDpi (Resolution)
$PCX_MAP['VDpi'] = 2; // VDpi (Resolution)
$PCX_MAP['colormap'] = 48; // Colormap
$PCX_MAP['Reserved'] = 1; // Reserved = 0
$PCX_MAP['NumberColorPlanes'] = 1; // Number of color planes
$PCX_MAP['BytesPerLine'] = 2; // Bytes Per Line
$PCX_MAP['PalleteInfo'] = 2; // Palette Info
$PCX_MAP['HorizontalScreenSize'] = 2; // H Screen Size
$PCX_MAP['VerticalScreenSize'] = 2; // V Screen Size
$PCX_MAP['Filler'] = 54; // Filler
$length = reset($PCX_MAP);
while (!feof($handle)) {
if ($length !== false) {
$contents = fread($handle, $length);
$contents = ord($contents);
echo key($PCX_MAP) . " : {$contents}\n";
$content .= $contents;
$length = next($PCX_MAP);
}
else {
// Get the rest 1 By 1
$contents = fread($handle, 1);
$contents = ord($contents);
$contents = intToBits($contents);
echo $contents ."\n";
}
}
fclose($handle);
/*
$data = file_get_contents($file);
for($i = 0; $i < strlen($data); ++$i) {
$char = ord($data[$i]);
echo "Byte $i: $char\n";
}*/
However, I am still attempting to parse the image data.
This currently returns this:
Manufacturer : 10
Version : 5
Encoding : 1
BitsPerPixel : 1
Xmin : 0
Ymin : 0
Xmax : 3
Ymax : 1
HDpi : 200
VDpi : 200
colormap : 15
Reserved : 0
NumberColorPlanes : 1
BytesPerLine : 2
PalleteInfo : 1
HorizontalScreenSize : 0
VerticalScreenSize : 0
Filler : 0
10000000
11000000
11111110
00000000
11000000
11111110
00000000
The header information is correct, but I'm not sure about the data after filler.
The graphic ran in this instance is a 4 x 2 - 0 means white, 1 means black
0101
1010
Try this:
while (!feof($handle)) {
$contents = fread($handle, 1);
$contents = $contents && 0xFF;
echo $contents;
$content .= $contents;
}
Related
I have a piece source code to search with Boolean retrieval
<?php
$path = "Korpus";
foreach(glob("$path/*.txt") as $file) {
foreach(file($file) as $line) {
echo $line."<br>";
}
}
$file = "";
$conv = "";
for($i = 1; $i < 4; $i++){
$file[$i] = file_get_contents("$path/Doc".$i.".txt");
$conv[$i] = explode(" ", strtolower($file[$i]));
echo "<br>";
print_r ($conv[$i]);
}echo "<br><br>";
?>
This is my Query
One AND Two AND NOT Three
I want the result like this
Term Doc1 Doc2 Doc3
One 1 0 0
Two 0 1 1
Three 0 1 0
Result : Doc1, Doc3
can someone help me to solve this problem ?
Im trying to make a script to get information in a file. The data in the file has this format:
#index|info1|info2|info3|info4|#index2|info21|info22|info23|info24
So I have to make a binary search direct on the file, look for the index and get all its information. For example:
$index = "index2";
Output: index2 info21 info22 info24
I tried:
$file = "file.txt";
// open the file for reading
$myfile = fopen($file, "r") or die("File cannot be openned");
$indexToSearch = "9780857293039";
$begging = 0;
$end = filesize($file) / sizeof($indexToSearch) - 1;
while($begging <= $end) {
$middle = ($end + $begging) / 2; );
$line = fread($myfile, $middle);
if(strcmp($line,$indexToSearch) == 0) {
echo "found";
break;
} else
if(strcmp($line,$indexToSearch) > 0) {
$end = $middle - 1;
} else {
$begging = $middle + 1;
}
}
fseek($myfile, $middle);
echo "<br><br>FINAL: ".fgets($myfile);
say you have a mp3 file.
Is it possible to extract the volume level(set between 0 and 100) for every byte in a mp3 file using PHP ?
This is what I already have, it might help you
function peaks($filename)
{
if (!file_exists($filename)) {
return false;
}
$bitRates = array(
array(0,0,0,0,0),
array(32,32,32,32,8),
array(64,48,40,48,16),
array(96,56,48,56,24),
array(128,64,56,64,32),
array(160,80,64,80,40),
array(192,96,80,96,48),
array(224,112,96,112,56),
array(256,128,112,128,64),
array(288,160,128,144,80),
array(320,192,160,160,96),
array(352,224,192,176,112),
array(384,256,224,192,128),
array(416,320,256,224,144),
array(448,384,320,256,160),
array(-1,-1,-1,-1,-1),
);
$sampleRates = array(
array(11025,12000,8000), //mpeg 2.5
array(0,0,0),
array(22050,24000,16000), //mpeg 2
array(44100,48000,32000), //mpeg 1
);
$bToRead = 1024 * 12;
$fileData = array('bitRate' => 0, 'sampleRate' => 0, 'bits' => 0);
$fp = fopen($filename, 'r');
if (!$fp) {
return false;
}
//seek to 8kb before the end of the file
fseek($fp, -1 * $bToRead, SEEK_END);
$data = fread($fp, $bToRead);
$bytes = unpack('C*', $data);
$frames = array();
$lastFrameVerify = null;
for ($o = 1; $o < count($bytes) - 4; $o++) {
//http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html
//header is AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
if (($bytes[$o] & 255) == 255 && ($bytes[$o+1] & 224) == 224) {
$frame = array();
$frame['version'] = ($bytes[$o+1] & 24) >> 3; //get BB (0 -> 3)
$frame['layer'] = abs((($bytes[$o+1] & 6) >> 1) - 4); //get CC (1 -> 3), then invert
$srIndex = ($bytes[$o+2] & 12) >> 2; //get FF (0 -> 3)
$brRow = ($bytes[$o+2] & 240) >> 4; //get EEEE (0 -> 15)
$frame['padding'] = ($bytes[$o+2] & 2) >> 1; //get G
if ($frame['version'] != 1 && $frame['layer'] > 0 && $srIndex < 3 && $brRow != 15 && $brRow != 0 &&
(!$lastFrameVerify || $lastFrameVerify === $bytes[$o+1])) {
//valid frame header
//calculate how much to skip to get to the next header
$frame['sampleRate'] = $sampleRates[$frame['version']][$srIndex];
if ($frame['version'] & 1 == 1) {
$frame['bitRate'] = $bitRates[$brRow][$frame['layer']-1]; //v1 and l1,l2,l3
} else {
$frame['bitRate'] = $bitRates[$brRow][($frame['layer'] & 2 >> 1)+3]; //v2 and l1 or l2/l3 (3 is the offset in the arrays)
}
if ($frame['layer'] == 1) {
$frame['frameLength'] = (12 * $frame['bitRate'] * 1000 / $frame['sampleRate'] + $frame['padding']) * 4;
} else {
$frame['frameLength'] = 144 * $frame['bitRate'] * 1000 / $frame['sampleRate'] + $frame['padding'];
}
$frames[] = $frame;
$lastFrameVerify = $bytes[$o+1];
$o += floor($frame['frameLength'] - 1);
} else {
$frames = array();
$lastFrameVerify = null;
}
}
if (count($frames) < 3) { //verify at least 3 frames to make sure its an mp3
continue;
}
$header = array_pop($frames);
$fileData['sampleRate'] = $header['sampleRate'];
$fileData['bitRate'] = $header['bitRate'];
$fileData['bits'] = $bytes;
break;
}
return $fileData;
}
If this works it will be used to generate waveforms from mp3 files.
this class can be a good starting point too :
http://www.phpclasses.org/browse/file/26606.html
use case here :
http://www.phpclasses.org/browse/file/26607.html
The code below sends a msg when a value, obtained from a not so stable API, is within a certain range.
This code causes the load average, but not the CPU usage, to go up, likely due to high I/O wait.
CentOS 6.5
Kernel 2.6.32-431.11.2.el6.x86_64
Apache 2.2.15
PHP 5.3.3 (mod_fcgid/2.3.7)
> cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
The code had the same problematic effect on both dedicated hardware and on the cloud (both cases as a VM on KVM/Virtio).
What could be done to keep this code from *causing the processor to wait on instruction completion before processing new instructions**? I understand that lowering the timeout doesn't really solve the problem, only diminishes its impact.
*this is my understanding why this code causes load average to go up.
<?php
$min = '1';
$last_min = '1';
if (!empty($_GET['min'])) {
$min = $_GET['min'];
} else {
$min = false;
}
$ctx=stream_context_create(array('http'=>
array(
'timeout' => 10 // seconds timeout
)
));
$json = file_get_contents('https://www.domain.com/api/ticker/',false,$ctx);
if (!empty($json )) {
echo($json);
if (#file_get_contents('log.txt')) {
if (quote_changed($json)) {
file_put_contents('log.txt', $json, FILE_APPEND);
}
} else {
file_put_contents('log.txt', $json);
}
$obj = json_decode($json,true);
$last = $obj['ticker']['last'];
if (is_numeric($last)) {
$last = (int)$last;
$last_min = #file_get_contents('last_min.txt');
$notified = #file_get_contents('notified.txt');
if ($notified === false) {
$notified = 'false';
#echo "no notify file\n";
}
if (($last_min === false) || (($min) && ($last_min <> $min))) {
$last_min = 1;
$notified = 'false';
file_put_contents('last_min.txt', $min);
#echo "no min file or diff min\n";
}
#echo ('notified='.$notified.'\n');
if (($last >= $min) && ($notified=='false')) {
#$url = ('http://otherdomain.com/nexmo/sendmsg.php' . '?name=blah' . $last);
#file_get_contents($url);
#switch to SMS when going abroad and plugin new number when available
mail("8885551212#mail.net","Blah at".$last,"","From: gaia#domain.com\n");
file_put_contents('notified.txt', 'true');
#echo "msg sent\n";
} elseif (($last < $min) && ($notified=='true')) {
file_put_contents('notified.txt', 'false');
#echo "not sent\n";
}
}
}
function quote_changed($current) {
$previous = tailCustom('log.txt');
#echo ('previous='.$previous);
if ($previous === (trim($current))) {
return 0;
} else {
return 1;
}
}
function tailCustom($filepath, $lines = 1, $adaptive = true) {
// Open file
$f = #fopen($filepath, "rb");
if ($f === false) return false;
// Sets buffer size
if (!$adaptive) $buffer = 4096;
else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));
// Jump to last character
fseek($f, -1, SEEK_END);
// Read it and adjust line number if necessary
// (Otherwise the result would be wrong if file doesn't end with a blank line)
if (fread($f, 1) != "\n") $lines -= 1;
// Start reading
$output = '';
$chunk = '';
// While we would like more
while (ftell($f) > 0 && $lines >= 0) {
// Figure out how far back we should jump
$seek = min(ftell($f), $buffer);
// Do the jump (backwards, relative to where we are)
fseek($f, -$seek, SEEK_CUR);
// Read a chunk and prepend it to our output
$output = ($chunk = fread($f, $seek)) . $output;
// Jump back to where we started reading
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
// Decrease our line counter
$lines -= substr_count($chunk, "\n");
}
// While we have too many lines
// (Because of buffer size we might have read too many)
while ($lines++ < 0) {
// Find first newline and remove all text before that
$output = substr($output, strpos($output, "\n") + 1);
}
// Close file and return
fclose($f);
return trim($output);
}
?>
Move the data into a database or if that's not an option, cache the unstable file into your server locally so you don't have to hit the external provider every time.
If neither of those are an option, it seems to me that the people providing the API need to improve their performance, you can verify this by just benchmarking how many milliseconds each hit takes through Firebug.
Similar to: How to read only 5 last line of the text file in PHP?
I have a large log file and I want to be able to show 100 lines from position X in the file.
I need to use fseek rather than file() because the log file is too large.
I have a similar function but it will only read from the end of the file. How can it be modified so that a start position can be specified as well? I would also need to start at the end of the file.
function read_line($filename, $lines, $revers = false)
{
$offset = -1;
$i = 0;
$fp = #fopen($filename, "r");
while( $lines && fseek($fp, $offset, SEEK_END) >= 0 ) {
$c = fgetc($fp);
if($c == "\n" || $c == "\r"){
$lines--;
if($revers){
$read[$i] = strrev($read[$i]);
$i++;
}
}
if($revers) $read[$i] .= $c;
else $read .= $c;
$offset--;
}
fclose ($fp);
if($revers){
if($read[$i] == "\n" || $read[$i] == "\r")
array_pop($read);
else $read[$i] = strrev($read[$i]);
return implode('',$read);
}
return strrev(rtrim($read,"\n\r"));
}
What I'm trying to do is create a web based log viewer that will start from the end of the file and display 100 lines, and when pressing the "Next" button, the next 100 lines preceding it will be shown.
If you're on Unix, you can utilize the sed tool. For example: to get line 10-20 from a file:
sed -n 10,20p errors.log
And you can do this in your script:
<?php
$page = 1;
$limit = 100;
$off = ($page * $limit) - ($limit - 1);
exec("sed -n $off,".($limit+$off-1)."p errors.log", $out);
print_r($out);
The lines are available in $out array.
This uses fseek to read 100 lines of a file starting from a specified offset. If the offset is greater than the number of lines in the log, the first 100 lines are read.
In your application, you could pass the current offset through the query string for prev and next and base the next offset on that. You could also store and pass the current file position for more efficiency.
<?php
$GLOBALS["interval"] = 100;
read_log();
function read_log()
{
$fp = fopen("log", "r");
$offset = determine_offset();
$interval = $GLOBALS["interval"];
if (seek_to_offset($fp, $offset) != -1)
{
show_next_button($offset, $interval);
}
$lines = array();
for ($ii = 0; $ii < $interval; $ii++)
{
$lines[] = trim(fgets($fp));
}
echo "<pre>";
print_r(array_reverse($lines));
}
// Get the offset from the query string or default to the interval
function determine_offset()
{
$interval = $GLOBALS["interval"];
if (isset($_GET["offset"]))
{
return intval($_GET["offset"]) + $interval;
}
return $interval;
}
function show_next_button($offset, $interval)
{
$next_offset = $offset + $interval;
echo "Next";
}
// Seek to the end of the file, then seek backward $offset lines
function seek_to_offset($fp, $offset)
{
fseek($fp, 0, SEEK_END);
for ($ii = 0; $ii < $offset; $ii++)
{
if (seek_to_previous_line($fp) == -1)
{
rewind($fp);
return -1;
}
}
}
// Seek backward by char until line break
function seek_to_previous_line($fp)
{
fseek($fp, -2, SEEK_CUR);
while (fgetc($fp) != "\n")
{
if (fseek($fp, -2, SEEK_CUR) == -1)
{
return -1;
}
}
}
Is "position X" measured in lines or bytes? If lines, you can easily use SplFileObject to seek to a certain line and then read 100 lines:
$file = new SplFileObject('log.txt');
$file->seek(199); // go to line 200
for($i = 0; $i < 100 and $file->valid(); $i++, $file->next())
{
echo $file->current();
}
If position X is measured in bytes, isn't it a simple matter of changing your initial $offset = -1 to a different value?
I would do it as followed:
function readFileFunc($tempFile){
if(#!file_exists($tempFile)){
return FALSE;
}else{
return file($tempFile);
}
}
$textArray = readFileFunc('./data/yourTextfile.txt');
$slicePos = count($textArray)-101;
if($slicePos < 0){
$slicePos = 0;
}
$last100 = array_slice($textArray, $slicePos);
$last100 = implode('<br />', $last100);
echo $last100;