import os
import logging
logger = logging.getLogger(__name__)
class PdfImageExporter:
imageStartMark = "\xff\xd8"
imageDataStartOffset = 0
imageEndMark = "\xff\xd9"
imageDataEndOffset = 2
streamHead = "stream"
streamEnd = "endstream"
offsetRange = 20
def export(self, pdfFile, outputDir=None):
pdfFile = os.path.abspath(pdfFile)
if outputDir == None:
outputDir = os.path.join(os.path.dirname(pdfFile),
os.path.basename(pdfFile)+"_img")
if not os.path.exists(outputDir):
os.makedirs(outputDir)
pdfContent = file(pdfFile, "rb").read()
imageIndex = 1
cursor = 0
while True:
streamStartIndex = pdfContent.find(self.streamHead, cursor)
if streamStartIndex < 0:
break
imageStartIndex = pdfContent.find(
self.imageStartMark, streamStartIndex, streamStartIndex+self.offsetRange)
if imageStartIndex < 0:
cursor = streamStartIndex + self.offsetRange
continue
streamEndIndex = pdfContent.find(self.streamEnd, imageStartIndex)
if streamEndIndex < 0:
raise Exception("Can not find end of stream")
imageEndIndex = pdfContent.find(self.imageEndMark, streamEndIndex-self.offsetRange)
if imageEndIndex < 0:
raise Exception("Can not find end of JPG")
imageDataStartIndex = imageStartIndex + self.imageDataStartOffset
imageDataEndIndex = imageEndIndex + self.imageDataEndOffset
# log
logger.info("JPG {0} from {1} to {2}".format(
imageIndex, imageDataStartIndex, imageDataEndIndex))
pdfFileName = os.path.splitext(os.path.basename(pdfFile))[0]
outFileName = "{0}_{1}.jpg".format(pdfFileName, imageIndex)
outFilePath = os.path.join(outputDir, outFileName)
file(outFilePath, "wb").write(pdfContent[imageDataStartIndex:imageDataEndIndex])
imageIndex += 1
cursor = imageDataEndIndex
|
// Server
public static class Server
{
private static string pipeName = "my pipe";
private static bool keepListening = true;
private static int maxNumberOfServerInstances = 5;
private static int countOfActiveInstances = 0;
public void StartListening()
{
keepListening = true;
new Thread(() => { ListeningThread(); }).Start();
}
private void ListeningThread()
{
NamedPipeServerStream ps = new NamedPipeServerStream(
pipeName, PipeDirection.InOut, maxNumberOfServerInstances);
countOfActiveInstances++;
ps.WaitForConnection();
// Create another thread for next connection
if (keepListening
&& countOfActiveInstances < maxNumberOfServerInstances)
{
new Thread(() => { ListeningThread(); }).Start();
}
HandleRequest(ps);
}
private void HandleRequest(NamedPipeServerStream ps)
{
string content = NamedPipeHelper.ReadDataWithDataSizeHeader(ps);
// handle request ...
countOfActiveInstances--;
}
}
// Client: just invoke 'SendDataToPipeServer'or 'SendToAndReceiveDataFromPipeServer'
// Util
public class NamedPipeHelper
{
/// <summary>
/// Caution: Pipe will be closed after invoking this method
/// </summary>
public static void SendDataToPipeServer(string serverPipeName, string data)
{
using (NamedPipeClientStream ps = new NamedPipeClientStream(serverPipeName))
{
ps.Connect();
WriteDataWithDataSizeHeader(ps, data);
}
}
/// <summary>
/// Caution: Pipe will be closed after invoking this method
/// </summary>
public static string SendToAndReceiveDataFromPipeServer(string serverPipeName, string data)
{
using (NamedPipeClientStream ps = new NamedPipeClientStream(serverPipeName))
{
ps.Connect();
WriteDataWithDataSizeHeader(ps, data);
return ReadDataWithDataSizeHeader(ps);
}
}
public static void WriteDataWithDataSizeHeader(Stream stream, string data)
{
byte[] bytesToWrite = Encoding.Unicode.GetBytes(data);
// Write the length of actual data
long lengthOfBytes = bytesToWrite.LongLength;
byte[] bytesOfLength = BitConverter.GetBytes(lengthOfBytes);
stream.Write(bytesOfLength, 0, bytesOfLength.Length);
stream.Flush();
// Send actual data
byte[] tmpBytesToWrite = new byte[4096];
long numberOfBytesHaveWritten = 0;
while (numberOfBytesHaveWritten < lengthOfBytes)
{
int lengthOfTmpBytes =
lengthOfBytes - numberOfBytesHaveWritten > tmpBytesToWrite.Length
? tmpBytesToWrite.Length
: (int)(lengthOfBytes - numberOfBytesHaveWritten);
Array.Copy(bytesToWrite, numberOfBytesHaveWritten, tmpBytesToWrite, 0, lengthOfTmpBytes);
stream.Write(tmpBytesToWrite, 0, lengthOfTmpBytes);
stream.Flush();
numberOfBytesHaveWritten += lengthOfTmpBytes;
}
}
public static string ReadDataWithDataSizeHeader(Stream stream)
{
// Read the length of actual data
byte[] bytesOfLength = new byte[sizeof(long)];
stream.Read(bytesOfLength, 0, bytesOfLength.Length);
long lengthOfBytes = BitConverter.ToInt64(bytesOfLength, 0);
// Read actual data
byte[] resultBytes = new byte[lengthOfBytes];
byte[] tmpBytesRead = new byte[4096];
long numberOfBytesHaveRead = 0;
while (numberOfBytesHaveRead < lengthOfBytes)
{
int lengthOfTmpBytes =
lengthOfBytes - numberOfBytesHaveRead > tmpBytesRead.Length
? tmpBytesRead.Length
: (int)(lengthOfBytes - numberOfBytesHaveRead);
stream.Read(tmpBytesRead, 0, lengthOfTmpBytes);
Array.Copy(tmpBytesRead, 0, resultBytes, numberOfBytesHaveRead, lengthOfTmpBytes);
numberOfBytesHaveRead += lengthOfTmpBytes;
}
return Encoding.Unicode.GetString(resultBytes);
}
}
|
public static class IniHelper
{
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL",
EntryPoint = "GetPrivateProfileStringW",
SetLastError = true,
CharSet = System.Runtime.InteropServices.CharSet.Unicode, ExactSpelling = true,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int GetPrivateProfileString(
string section,
string key,
string defaultValue,
string returnString,
int size,
string iniFile);
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL",
EntryPoint = "WritePrivateProfileStringW",
SetLastError = true,
CharSet = System.Runtime.InteropServices.CharSet.Unicode, ExactSpelling = true,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int WritePrivateProfileString(
string section,
string key,
string value,
string iniFile);
/// <summary>
/// Get all sections in a ini file
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <returns></returns>
public static List<string> GetIniSections(string iniFile)
{
string returnString = new string(' ', 65536);
GetPrivateProfileString(null, null, null, returnString, 65536, iniFile);
List<string> result = returnString.Split('\0').ToList();
result.RemoveRange(result.Count - 2, 2);
return result;
}
/// <summary>
/// Get all keys under a section
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <param name="section">target section name</param>
/// <returns></returns>
public static List<string> GetIniKeys(string iniFile, string section)
{
string returnString = new string(' ', 32768);
GetPrivateProfileString(section, null, null, returnString, 32768, iniFile);
List<string> result = returnString.Split('\0').ToList();
result.RemoveRange(result.Count - 2, 2);
return result;
}
/// <summary>
/// Get value of a key
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <param name="section">target section</param>
/// <param name="key">target key</param>
/// <param name="defaultValue">default value</param>
/// <returns></returns>
public static string GetIniValue(string iniFile, string section, string key, string defaultValue)
{
string rs = new string(' ', 1024);
GetPrivateProfileString(section, key, defaultValue, rs, 1024, iniFile);
return rs.Split('\0')[0];
}
/// <summary>
/// Load ini key and value under a section
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <param name="section">target section</param>
/// <returns></returns>
public static List<KeyValuePair<string, string>> LoadIniKeyValuePair(string iniFile, string section)
{
List<KeyValuePair<string, string>> pairs = new List<KeyValuePair<string, string>>();
IEnumerable<string> keys = GetIniKeys(iniFile, section);
foreach (string key in keys)
{
pairs.Add(new KeyValuePair<string, string>(key, GetIniValue(iniFile, section, key, "N/A")));
}
return pairs;
}
/// <summary>
/// Save all data under a section
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <param name="section">target section</param>
/// <param name="pairs">data to save</param>
public static void SaveEntireSection(string iniFile, string section, IEnumerable<KeyValuePair<string, string>> pairs)
{
//Clear original data
WritePrivateProfileString(section, null, null, iniFile);
//Save new data
SaveIniKeyValuePair(iniFile, section, pairs);
}
/// <summary>
/// Save data under a section
/// </summary>
/// <param name="iniFile">target ini file</param>
/// <param name="section">target section</param>
/// <param name="pairs">data to save</param>
public static void SaveSection(string iniFile, string section, IEnumerable<KeyValuePair<string, string>> pairs)
{
//Clear original data
foreach (KeyValuePair<string, string> pair in pairs)
{
WritePrivateProfileString(section, pair.Key, null, iniFile);
}
//Save new data
SaveIniKeyValuePair(iniFile, section, pairs);
}
/// <summary>
/// Save data under a section
/// </summary>
/// <param name="iniFile">targe ini file</param>
/// <param name="section">target section</param>
/// <param name="pairs">data to save</param>
public static void SaveIniKeyValuePair(string iniFile, string section, IEnumerable<KeyValuePair<string, string>> pairs)
{
foreach (KeyValuePair<string, string> pair in pairs)
{
WritePrivateProfileString(section, pair.Key, pair.Value, iniFile);
}
}
}
|