Example #1
0
        public void ScanImageReadLine
        (
            Object sender,
            DataReceivedEventArgs e
        )
        {
            lock (objectScanImageReadLine)
            {
                bool blSuccess;
                bool blEndOfJob = false;
                int  iImageNumber;

                // Log it, note that we may not get everything because .NET can
                // fumble the standard output.  This isn't a problem, it's just
                // nice to show what we can get...
                if (e == null)
                {
                    Log.Info("scanimage>>> (program exited)");
                    blEndOfJob = true;
                }
                else if (string.IsNullOrEmpty(e.Data))
                {
                    Log.Info("scanimage>>> (no data)");
                    return;
                }
                else
                {
                    Log.Info("scanimage>>> " + e.Data);
                    if (!e.Data.StartsWith("Scanned page"))
                    {
                        return;
                    }
                }

                // Get the list of files...
                string[] aszPnm = Directory.GetFiles(m_szImagesFolder);
                if (aszPnm == null)
                {
                    if (blEndOfJob)
                    {
                        SetEndOfJob("SUCCESS");
                    }
                    return;
                }

                // Convert all .pnm files into .pdf and metadata...
                foreach (string szPnm in aszPnm)
                {
                    string szMeta;
                    byte[] abPnm;

                    // Skip stuff that isn't .pnm...
                    if (!szPnm.EndsWith(".pnm"))
                    {
                        continue;
                    }

                    // Load the .pnm data...
                    Log.Info("scanimage>>> load " + szPnm);
                    try
                    {
                        abPnm = File.ReadAllBytes(szPnm);
                    }
                    catch
                    {
                        // We'll assume that the file isn't ready for us yet,
                        // so bail...
                        Log.Info("scanimage>>> ReadAllBytes failed (file may be in use)...");
                        if (blEndOfJob)
                        {
                            SetEndOfJob("SUCCESS");
                        }
                        return;
                    }

                    // Convert the first 40 bytes to ANSI...
                    string   szHeader  = Encoding.ASCII.GetString(abPnm, 0, 40);
                    string[] aszHeader = szHeader.Split(new char[] { '\n', '\r' });

                    // Get the pixelformat and the stride...
                    int    iStride       = 0;
                    int    iWidth        = 0;
                    int    iHeight       = 0;
                    int    iImageOffset  = 0;
                    string szPixelFormat = aszHeader[0];
                    string szTwainDirectPixelFormat;
                    switch (szPixelFormat)
                    {
                    default:
                        TwainDirect.Support.Log.Info("scanimage>>> Not supported pixel format..." + szHeader);
                        continue;

                    case "P4":
                        szTwainDirectPixelFormat = "bw1";
                        iImageOffset             = (aszHeader[0].Length + 1) + (aszHeader[1].Length + 1) + (aszHeader[2].Length + 1);
                        break;

                    case "P5":
                        szTwainDirectPixelFormat = "gray8";
                        iImageOffset             = (aszHeader[0].Length + 1) + (aszHeader[1].Length + 1) + (aszHeader[2].Length + 1) + (aszHeader[3].Length + 1);
                        break;

                    case "P6":
                        szTwainDirectPixelFormat = "rgb25";
                        iImageOffset             = (aszHeader[0].Length + 1) + (aszHeader[1].Length + 1) + (aszHeader[2].Length + 1) + (aszHeader[3].Length + 1);
                        break;
                    }

                    // Get the width and the height...
                    string[] aszDim = aszHeader[2].Split(new char[] { ' ' });
                    int.TryParse(aszDim[0], out iWidth);
                    int.TryParse(aszDim[1], out iHeight);

                    // Get the image data...
                    byte[] abImage = new byte[abPnm.Length - iImageOffset];
                    Buffer.BlockCopy(abPnm, iImageOffset, abImage, 0, abPnm.Length - iImageOffset);

                    // Stupid bitonal data, you had a 50/50 shot!
                    if (szPixelFormat == "P4")
                    {
                        for (int bb = 0; bb < abImage.Length; bb++)
                        {
                            abImage[bb] = (byte)~abImage[bb];
                        }
                    }

                    // Infer the stride from the image size / by the height...
                    iStride = abImage.Length / iHeight;

                    // Get a byte array from the image...
                    Log.Info("scanimage>>> done: format=" + szPixelFormat + " " + iWidth + "x" + iHeight + " res=" + SaneTask.ms_szResolution + " stride=" + iStride);

                    // So far so good, let's extract the image number...
                    if (!int.TryParse(Path.GetFileNameWithoutExtension(szPnm).Replace("img", ""), out iImageNumber))
                    {
                        Log.Info("scanimage>>> failed to get the image number...");
                        continue;
                    }

                    // Create the .pdf...
                    string szPdfFile = szPnm.Remove(szPnm.Length - 4, 4) + ".pdf";
                    Log.Info("scanimage>>> creating pdf " + szPdfFile);
                    blSuccess = PdfRaster.CreatePdfRaster
                                (
                        szPdfFile,
                        "",
                        abImage,
                        0,
                        szTwainDirectPixelFormat,
                        "none",
                        int.Parse(SaneTask.ms_szResolution),
                        iWidth,
                        iHeight
                                );
                    if (!blSuccess)
                    {
                        Log.Error("ReportImage: unable to save the image file..." + szPdfFile);
                        //m_blProcessing = false;
                        //m_blCancel = false;
                        SetEndOfJob("FILEWRITEERROR");
                        return;
                    }
                    Log.Info("scanimage>>> done...");

                    // TWAIN Direct metadata...
                    szMeta = "";

                    // TWAIN Direct metadata.address begin...
                    szMeta += "        \"metadata\": {\n";

                    // TWAIN Direct metadata.address begin...
                    szMeta += "            \"address\": {\n";

                    // Imagecount (counts images)...
                    szMeta += "                \"imageNumber\": " + m_iImageCount + ",\n";

                    // Sheetcount (counts sheets, including ones lost to blank image dropout)...
                    szMeta += "                \"sheetNumber\": " + "1" + ",\n";

                    // The image came from a flatbed or a feederFront or whatever...
                    if ((iImageNumber & 1) == 1)
                    {
                        szMeta += "                \"source\": \"" + "feederFront" + "\"\n";
                    }
                    else
                    {
                        szMeta += "                \"source\": \"" + "feederRear" + "\"\n";
                    }

                    // TWAIN Direct metadata.address end...
                    szMeta += "            },\n";

                    // TWAIN Direct metadata.image begin...
                    szMeta += "            \"image\": {\n";

                    // Add compression...
                    szMeta += "                \"compression\": \"" + "none" + "\",\n";

                    // Add pixel format...
                    switch (szPixelFormat)
                    {
                    default:
                    case "P4":
                        szMeta += "                \"pixelFormat\": \"" + "bw1" + "\",\n";
                        break;

                    case "P5":
                        szMeta += "                \"pixelFormat\": \"" + "gray8" + "\",\n";
                        break;

                    case "P6":
                        szMeta += "                \"pixelFormat\": \"" + "rgb24" + "\",\n";
                        break;
                    }

                    // Add height...
                    szMeta += "                \"pixelHeight\": " + iHeight + ",\n";

                    // X-offset...
                    szMeta += "                \"pixelOffsetX\": " + "0" + ",\n";

                    // Y-offset...
                    szMeta += "                \"pixelOffsetY\": " + "0" + ",\n";

                    // Add width...
                    szMeta += "                \"pixelWidth\": " + iWidth + ",\n";

                    // Add resolution...
                    szMeta += "                \"resolution\": " + SaneTask.ms_szResolution + ",\n";

                    // Add size...
                    FileInfo fileinfo = new FileInfo(szPnm);
                    szMeta += "                \"size\": " + fileinfo.Length + "\n";

                    // TWAIN Direct metadata.image end...
                    szMeta += "            },\n";

                    // TWAIN Direct metadata.address begin...
                    szMeta += "            \"imageBlock\": {\n";

                    // Imagecount (counts images)...
                    szMeta += "                \"imageNumber\": " + m_iImageCount + ",\n";

                    // Segmentcount (long document or huge document)...
                    szMeta += "                \"imagePart\": " + "1" + ",\n";

                    // Segmentlast (long document or huge document)...
                    szMeta += "                \"moreParts\": " + "\"lastPartInFile\"" + "\n";

                    // TWAIN Direct metadata.address end...
                    szMeta += "            },\n";

                    // Open SWORD.metadata.status...
                    szMeta += "            \"status\": {\n";

                    // Add the status...
                    szMeta += "                \"success\": true\n";

                    // TWAIN Direct metadata.status end...
                    szMeta += "            }\n";

                    // TWAIN Direct metadata end...
                    szMeta += "        }\n";

                    // Get rid of the .pnm file...
                    TwainDirect.Support.Log.Info("scanimage>>> deleting the pnm file...");
                    abImage = null;
                    abPnm   = null;
                    try
                    {
                        File.Delete(szPnm);
                    }
                    catch
                    {
                        // Don't really care...
                    }

                    // Save the metadata to disk...
                    try
                    {
                        string szMetaFile = szPnm.Remove(szPnm.Length - 4, 4) + ".meta";
                        File.WriteAllText(szMetaFile, szMeta);
                        Log.Info("ReportImage: saved " + szMetaFile);
                    }
                    catch
                    {
                        Log.Error("ReportImage: unable to save the metadata file...");
                        //m_blProcessing = false;
                        //m_blCancel = false;
                        SetEndOfJob("FILEWRITEERROR");
                        return;
                    }
                }

                // Looks like we're all done...
                if (blEndOfJob)
                {
                    SetEndOfJob("SUCCESS");
                    m_processScanImage = null;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Test the code...
        /// </summary>
        /// <returns></returns>
        public bool Test()
        {
            BinaryWriter binarywriter;
            PdfRaster    pdfraster = new PdfRaster();

            PdfRaster.t_OS os;
            byte[]         bitonalData     = new byte[((850 + 7) / 8) * 1100];
            string         OUTPUT_FILENAME = "raster.pdf";

            byte[] _imdata = new byte[]
            {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
                0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
                0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
                0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
                0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
                0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
                0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
                0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
            };

            // Create the file...
            binarywriter = new BinaryWriter(File.Create(OUTPUT_FILENAME));
            if (binarywriter == null)
            {
                TWAINWorkingGroup.Log.Error("unable to open %s for writing " + OUTPUT_FILENAME);
                return(false);
            }

            // Set up our worker functions...
            os                = new PdfRaster.t_OS();
            os.alloc          = null;
            os.free           = null;
            os.memset         = null;
            os.memclear       = null;
            os.allocsys       = PdfRaster.pd_alloc_sys_new(os);
            os.writeout       = myOutputWriter;
            os.writeoutcookie = binarywriter;

            // Construct a raster PDF encoder
            object enc = pdfraster.pd_raster_encoder_create(PdfRaster.PdfRasterConst.PDFRAS_API_LEVEL, os);

            PdfRaster.pd_raster_set_creator(enc, "raster_encoder_demo 1.0");

            // First page - 4" x 5.5" at 2 DPI
            PdfRaster.pd_raster_set_resolution(enc, 2.0, 2.0);
            // start a new page
            pdfraster.pd_raster_encoder_start_page(enc, PdfRaster.RasterPixelFormat.PDFRAS_GRAYSCALE, PdfRaster.RasterCompression.PDFRAS_UNCOMPRESSED, 8);
            // write a strip of raster data to the current page
            // 11 rows high
            pdfraster.pd_raster_encoder_write_strip(enc, 11, _imdata, 0, (UInt32)_imdata.Length);
            // the page is done
            pdfraster.pd_raster_encoder_end_page(enc);

            // Next page: bitonal 8.5 x 11 at 100 DPI with a light dotted grid
            // generate page data
            for (int i = 0; i < bitonalData.Length; i++)
            {
                int y = (i / 107);
                int b = (i % 107);
                if ((y % 100) == 0)
                {
                    bitonalData[i] = 0xAA;
                }
                else if (((b % 12) == 0) && ((y & 1) != 0))
                {
                    bitonalData[i] = 0x7F;
                }
                else
                {
                    bitonalData[i] = 0xff;
                }
            }
            PdfRaster.pd_raster_set_resolution(enc, 100.0, 100.0);
            pdfraster.pd_raster_encoder_start_page(enc, PdfRaster.RasterPixelFormat.PDFRAS_BITONAL, PdfRaster.RasterCompression.PDFRAS_UNCOMPRESSED, 850);
            pdfraster.pd_raster_encoder_write_strip(enc, 1100, bitonalData, 0, (UInt32)bitonalData.Length);
            pdfraster.pd_raster_encoder_end_page(enc);

            // Third page: color 3.5" x 2" 50 DPI
            int stride = 3;

            byte[] colorData = new byte[175 * 100 * stride];
            for (int i = 0; i < colorData.Length; i += stride)
            {
                int y = ((i / stride) / 175);
                int x = ((i / stride) % 175);
                colorData[i + 0] = (byte)((i / stride) % 255);
                colorData[i + 1] = (byte)((x + y) % 255);
                colorData[i + 2] = (byte)((x - y + 9999) % 255);
            }
            PdfRaster.pd_raster_set_resolution(enc, 50.0, 50.0);
            pdfraster.pd_raster_encoder_start_page(enc, PdfRaster.RasterPixelFormat.PDFRAS_RGB, PdfRaster.RasterCompression.PDFRAS_UNCOMPRESSED, 175);
            pdfraster.pd_raster_encoder_write_strip(enc, 100, colorData, 0, (UInt32)colorData.Length);
            pdfraster.pd_raster_encoder_end_page(enc);

            // the document is complete
            pdfraster.pd_raster_encoder_end_document(enc);

            // clean up
            binarywriter.Flush();
            binarywriter.Close();
            pdfraster.pd_raster_encoder_destroy(enc);

            // All done...
            return(true);
        }
Example #3
0
        /// <summary>
        /// Start polling for work...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void m_buttonStart_Click(object sender, EventArgs e)
        {
            bool blSuccess;

            // Turn all the buttons off...
            SetButtons(ButtonState.Undefined);

            // Is PDF/raster happy and healthy?
            PdfRaster pdfraster = new PdfRaster();

            if (!pdfraster.HealthCheck())
            {
                DialogResult dialogresult = MessageBox.Show
                                            (
                    "We need to install the Visual Studio 2017 Redistributables for PDF/raster.  May we continue?",
                    "Warning",
                    MessageBoxButtons.YesNo
                                            );
                if (dialogresult == DialogResult.Yes)
                {
                    pdfraster.InstallVisualStudioRedistributables();
                }
            }

            // Start polling...
            Display("");
            Display("Starting, please wait...");
            if (Config.Get("imageBlockSize", 0) < 8192)
            {
                Display("Each image will be transferred in its own imageBlock...");
            }
            else
            {
                Display("imageBlocks will not exceed " + Config.Get("imageBlockSize", 0) + " bytes...");
            }
            string szNote = m_scanner.GetTwainLocalNote();

            if (!string.IsNullOrEmpty(szNote))
            {
                Display(m_scanner.GetTwainLocalTy() + " (" + szNote + ")");
            }
            else
            {
                Display(m_scanner.GetTwainLocalTy());
            }

            // Start monitoring the cloud...
            try
            {
                blSuccess = await m_scanner.MonitorTasksStart();

                if (!blSuccess)
                {
                    Log.Error("MonitorTasksStart failed...");
                    MessageBox.Show("Failed to start cloud monitoring, check the logs for more information.", Config.GetResource(m_resourcemanager, "strFormMainTitle"));
                    SetButtons(ButtonState.WaitingForStart);
                    return;
                }
            }
            catch (Exception exception)
            {
                Log.Error("MonitorTasksStart failed...");
                MessageBox.Show("Failed to start the cloud monitoring, check the logs for more information." + Environment.NewLine + "Error: " + exception.Message, Config.GetResource(m_resourcemanager, "strFormMainTitle"));
            }
            if (m_scanner.IsTwainLocalStarted())
            {
                Display("TWAIN Local is ready for use...");
            }
            if (m_scanner.IsTwainCloudStarted())
            {
                Display("TWAIN Cloud is ready for use...");
            }

            // Set buttons...
            SetButtons(ButtonState.Started);
        }