<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: IDRSolutions</title>
    <description>The latest articles on DEV Community by IDRSolutions (@idrsolutions).</description>
    <link>https://dev.to/idrsolutions</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3078638%2Faa7ba4ef-f446-48e3-95e9-0c43d0c3e214.png</url>
      <title>DEV Community: IDRSolutions</title>
      <link>https://dev.to/idrsolutions</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idrsolutions"/>
    <language>en</language>
    <item>
      <title>How to view Multi-TIFF files in Java (Tutorial)</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Wed, 09 Sep 2026 11:24:58 +0000</pubDate>
      <link>https://dev.to/idrsolutions/how-to-view-multi-tiff-files-in-java-tutorial-d53</link>
      <guid>https://dev.to/idrsolutions/how-to-view-multi-tiff-files-in-java-tutorial-d53</guid>
      <description>&lt;p&gt;In this article, I will show you how to read and view Multi-TIFF files in Java. We already have an article on &lt;a href="https://blog.idrsolutions.com/how-to-read-tiff-images-in-java/" rel="noopener noreferrer"&gt;How to read TIFF images in Java&lt;/a&gt;, why not check it out!&lt;/p&gt;

&lt;p&gt;JDeli helps you &lt;a href="https://www.idrsolutions.com/jdeli/tiff" rel="noopener noreferrer"&gt;read, write and convert TIFF files&lt;/a&gt; in pure Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Multi-TIFF file?
&lt;/h2&gt;

&lt;p&gt;TIFF (Tag Image File Format) files are able to contain multiple images. This is what we would call a Multi-TIFF file.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to view in Java?
&lt;/h2&gt;

&lt;p&gt;First you need to read the images into Java. The standard JDK does not support multi-tiff images so you will need to use an additional library such as JDeli. JDeli is the best pure Java image library for performance and efficiency. You can only store one image in a BufferedImage, so JDeli returns an image count and a method to read each image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;TiffDecoder&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TiffDecoder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;imageCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getImageCount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;BufferedImage&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readImageAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentIm&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the images as BufferedImages, they are easy to display in Java.&lt;/p&gt;

&lt;p&gt;If you have read my previous post on &lt;a href="https://blog.idrsolutions.com/how-to-view-images-in-java/" rel="noopener noreferrer"&gt;How to view images in Java&lt;/a&gt;, then you already have an image viewer in Java or you can clone our &lt;a href="https://github.com/idrsolutions/Java-Image-Viewer" rel="noopener noreferrer"&gt;Java Image Viewer GitHub repository&lt;/a&gt;. You can now modify it to view multi-TIFF images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional code needed to support Multi-Tiff files in Java Viewer
&lt;/h3&gt;

&lt;p&gt;First, you  need to read each image in the file and display it. You can achieve this by keeping a count of the images in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;TiffDecoder&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TiffDecoder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;imageCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getImageCount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then displaying them one by one with buttons to allow you to cycle through them, much like in our &lt;a href="https://www.idrsolutions.com/jdeli/?mtm_campaign=Blog-trial-downloads&amp;amp;mtm_kwd=blog%20articles&amp;amp;mtm_campaign=BlogTrialDownloads" rel="noopener noreferrer"&gt;JDeli viewer&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;currentIm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Next image"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Previous image"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addActionListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentIm&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;imageCount&lt;/span&gt; &lt;span class="err"&gt;–&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;currentIm&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
    &lt;span class="n"&gt;drawImage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addActionListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currIm&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;curentIm&lt;/span&gt;&lt;span class="err"&gt;–&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;drawImage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Add the buttons to the viewer&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JPanel&lt;/span&gt; &lt;span class="n"&gt;multiButtons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JPanel&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;multiButtons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;multiButtons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiButtons&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PAGE_END&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The draw image method would be one you’d use to set the image each time something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;BufferedImage&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tiff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readImageAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentIm&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;imageLabel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setIcon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ImageIcon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can view all the images in your multi-TIFF file!&lt;/p&gt;

&lt;p&gt;As experienced Java developers, we help you &lt;a href="https://blog.idrsolutions.com/working-with-images-in-java/" rel="noopener noreferrer"&gt;work with images in Java&lt;/a&gt; and bring over a decade of hands-on experience with many image file formats.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to copy bookmarks from one PDF to another</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:51:57 +0000</pubDate>
      <link>https://dev.to/idrsolutions/how-to-copy-bookmarks-from-one-pdf-to-another-54m6</link>
      <guid>https://dev.to/idrsolutions/how-to-copy-bookmarks-from-one-pdf-to-another-54m6</guid>
      <description>&lt;p&gt;JPedal already has the ability to &lt;a href="https://www.idrsolutions.com/docs/jpedal/tutorials/extract-text/extract-document-outline-from-any-pdf-file" rel="noopener noreferrer"&gt;read bookmarks from PDF files&lt;/a&gt; so now you can chain this functionality with our &lt;a href="https://javadoc.idrsolutions.com/org/jpedal/io/outline/OutlineWriter.html" rel="noopener noreferrer"&gt;OutlineWriter&lt;/a&gt; to copy bookmarks from one PDF to another. JPedal is the best Java PDF library for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Copy bookmarks using Java
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add JPedal to your class or module path. (Download the &lt;a href="https://www.idrsolutions.com/jpedal/#why-buy" rel="noopener noreferrer"&gt;trial JAR&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Next, read the outline into a &lt;a href="https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Document.html" rel="noopener noreferrer"&gt;Document&lt;/a&gt; object:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Read&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ExtractOutline&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExtractOutline&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"source.pdf"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openPDFFile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="n"&gt;outlines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPDFTextOutline&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closePDFfile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Then, write the Document object to the destination PDF:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Write&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;OutlineWriter&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OutlineWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"destination.pdf"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outlines&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeOutline&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Copy bookmarks using the command line
JPedal also provides a convenient command line method to copy bookmarks between PDF files:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; jpedal.jar –copyoutline &lt;span class="s2"&gt;"oldfile.pdf"&lt;/span&gt; &lt;span class="s2"&gt;"newfile.pdf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Working with PDFs can be troublesome. We have a list of different articles to help you &lt;a href="https://blog.idrsolutions.com/understanding-the-pdf-file-format/" rel="noopener noreferrer"&gt;understand the PDF format&lt;/a&gt; and maximise its functionality.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>pdf</category>
    </item>
    <item>
      <title>HTML and SVG Explained (Along with Use Cases)</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Fri, 28 Aug 2026 14:40:01 +0000</pubDate>
      <link>https://dev.to/idrsolutions/html-and-svg-explained-along-with-use-cases-1l7l</link>
      <guid>https://dev.to/idrsolutions/html-and-svg-explained-along-with-use-cases-1l7l</guid>
      <description>&lt;p&gt;In this article I will explain what HTML and SVG, how they’re related and which might be suited for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTML?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTML" rel="noopener noreferrer"&gt;HTML&lt;/a&gt; is the text-based language invented by Tim Berners-Lee at CERN to create web pages. It is displayed by Browsers (IE, Safari, Chrome, Firefox, etc).&lt;/p&gt;

&lt;p&gt;The HTML language is defined by an international committee that releases a public specification. We are currently on HTML Version 5 (HTML5). You will find minor differences (which we often document on this blog) in support across browsers but no ‘major’ issues with HTML5 support in the major browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does HTML work?
&lt;/h2&gt;

&lt;p&gt;This page you are reading is written in HTML but how does html code work? HTML contains both the text and instructions on how to display the text, links to images, etc. You might be wondering how HTML is used, I like to think of HTML as containing the page content, the structure of the page (HyperText Markup), and the style of the page (CSS).&lt;/p&gt;

&lt;p&gt;You can write it from scratch in a text editor, but most people use tools to create it. There is now a huge range of dedicated tools to do this and many other applications (like the &lt;a href="http://www.netbeans.org/" rel="noopener noreferrer"&gt;NetBeans IDE&lt;/a&gt;) also support it.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML5 Features
&lt;/h2&gt;

&lt;p&gt;HTML5 had some major additions to the HTML features including:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Canvas (for writing action games and animation).&lt;/li&gt;
&lt;li&gt;Support for video and sound&lt;/li&gt;
&lt;li&gt;Offline support&lt;/li&gt;
&lt;li&gt;Location functionality&lt;/li&gt;
&lt;li&gt;SVG support (so SVG is now part of HTML)&lt;/li&gt;
&lt;li&gt;Improved CSS support (which can also be used for animations and transitions).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTML also includes support for fillable forms and interactive elements. The pages can contain JavaScript code and be dynamically updated.&lt;/p&gt;

&lt;p&gt;HTML5 is the first version of HTML which we feel is good enough to make a decent conversion from PDF possible. You can try yourself and see what you think with our &lt;a href="https://www.idrsolutions.com/online-pdf-to-html5-converter" rel="noopener noreferrer"&gt;free PDF online converter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is what HTML looks like as a page and the raw HTML code. The HTML is text but can include links to images and other pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fogbvw2m8j5ink32j8d6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fogbvw2m8j5ink32j8d6m.png" alt="HTML example" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re working with PDFs and would like to convert them to HTML for your web applications, you can learn more about our product &lt;a href="https://www.idrsolutions.com/buildvu/pdf-to-html" rel="noopener noreferrer"&gt;BuildVu&lt;/a&gt;. BuildVu is the best tool for converting PDF to HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SVG?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics" rel="noopener noreferrer"&gt;SVG&lt;/a&gt; stands for Scalable Vector Graphics (although it can also include text and bitmaps). Such vector graphics do not lose their quality when zoomed or resized because they are scalable. This means that you define the content using simple text instructions, and when it is scaled, the browser will redraw it at the required resolution – so the Vector content is sharp with no pixelation at any resolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  SVG Support
&lt;/h2&gt;

&lt;p&gt;SVG has been around since 1999 (the joke was that it was the technology of the future and always would be). However, all modern browsers now support SVG either directly or as part of the HTML5 specification, so it is becoming increasingly common to use. It is based on XML and provides a text-based language to create shapes, text and embed images.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does SVG work?
&lt;/h2&gt;

&lt;p&gt;When SVG is used to build a page, more complicated pages can take longer to render. If you are interested in improving SVG files, my colleague Leon wrote a blog post describing &lt;a href="https://blog.idrsolutions.com/6-tips-optimising-svg-files/" rel="noopener noreferrer"&gt;six ways of optimising SVG files&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can embed forms and video in SVG as Foreign objects, but in general, it lacks the wide range of features available in HTML5. It has arguably better drawing capabilities than HTML5 and when we compare the results of HTML5 and SVG from our converter side by side, the SVG generally looks ‘better’ (you can see 2 examples on this page to compare).&lt;/p&gt;

&lt;p&gt;Here is what SVG looks like as a page and the raw SVG code. The SVG is text but can include links to images and other pages. You can use &lt;a href="https://www.idrsolutions.com/buildvu/pdf-to-svg" rel="noopener noreferrer"&gt;BuildVu&lt;/a&gt; to convert your PDFs to SVG for display on your own web applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyvtral93arofljraz5jf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyvtral93arofljraz5jf.png" alt="SVG example" width="799" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More examples of HTML and SVG
&lt;/h2&gt;

&lt;p&gt;Visit our BuildVu page to see more sample HTML and SVG files created from our PDF converter.&lt;/p&gt;

&lt;p&gt;There is a very popular library called &lt;a href="http://d3js.org/" rel="noopener noreferrer"&gt;D3.js&lt;/a&gt; that has been used for some amazing things.&lt;/p&gt;

&lt;p&gt;You can find an impressive example of animated SVG &lt;a href="http://bl.ocks.org/mbostock/1153292" rel="noopener noreferrer"&gt;here&lt;/a&gt; (click and drag the nodes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions – our take on HTML and SVG…
&lt;/h2&gt;

&lt;p&gt;Our experience of HTML5 and SVG from developing our PDF converter has been that both have their strengths and weaknesses.&lt;/p&gt;

&lt;p&gt;SVG is superior if you want a static display of vector content.&lt;/p&gt;

&lt;p&gt;If you want to write animation, HTML5 has a canvas mode.&lt;/p&gt;

&lt;p&gt;If you want to use JavaScript or Fillable forms HTML5 is the choice.&lt;/p&gt;

&lt;p&gt;In practice, the fact that SVG is part of HTML5 means that you can use them together and this is the choice we have adopted for &lt;a href="https://www.idrsolutions.com/online-pdf-to-html5-converter" rel="noopener noreferrer"&gt;our PDF converter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>html</category>
      <category>web</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Comparing PNG Compression Algorithms</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Thu, 27 Aug 2026 08:38:13 +0000</pubDate>
      <link>https://dev.to/idrsolutions/comparing-png-compression-algorithms-4cfb</link>
      <guid>https://dev.to/idrsolutions/comparing-png-compression-algorithms-4cfb</guid>
      <description>&lt;p&gt;In this article, we will be comparing the different compression methods available for use in &lt;a href="https://www.idrsolutions.com/jdeli/png" rel="noopener noreferrer"&gt;PNG images&lt;/a&gt;. To do this, we will be using our Java image library, &lt;a href="https://www.idrsolutions.com/jdeli/" rel="noopener noreferrer"&gt;JDeli&lt;/a&gt;. JDeli is the best pure Java image library for performance and efficiency. We will be comparing against file size, quality of output, and speed.&lt;/p&gt;

&lt;p&gt;For the baseline of our comparisons, we will be using the following image. It has a file size of 39.3MB and takes just under 5 seconds to encode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1we2ikguywx4j3b5g07f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1we2ikguywx4j3b5g07f.png" alt="PNG example image" width="800" height="814"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DEFLATE
&lt;/h2&gt;

&lt;p&gt;DEFLATE was designed in the 1990s and is most commonly using in ZIP file archives due to its lossless property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0p7dhankk66grqwt4tju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0p7dhankk66grqwt4tju.png" alt="Deflate PNG example" width="800" height="814"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using DEFLATE, the file size is reduced to 5.1MB taking around 6 seconds to encode. Since DEFLATE is lossless, the image quality is preserved and matches the original file.&lt;/p&gt;

&lt;h2&gt;
  
  
  QUANTISE
&lt;/h2&gt;

&lt;p&gt;QUANTISE is a lossy compression technique that reduces file size by limiting the range of available colours. It is commonly used in PNG and GIF images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2ee9o1sayw4qym746axf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2ee9o1sayw4qym746axf.png" alt="Quantise PNG example" width="800" height="814"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using QUANTISE, the file size is reduced to 3.5MB. QUANTISE is lossy, so there is a reduction in image quality, most noticeably in the range of colours which are output. It also takes around 6 seconds to encode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, there are not a great deal of options when it comes to different compression algorithms in PNG files. DEFLATE is a clear winner here as it reduces the file size with no loss of quality. QUANTISE would only be better when the smallest possible file size is necessary.&lt;/p&gt;

&lt;p&gt;As experienced Java developers, we help you &lt;a href="https://blog.idrsolutions.com/working-with-images-in-java/" rel="noopener noreferrer"&gt;work with images in Java&lt;/a&gt; and bring over a decade of hands-on experience with many image file formats.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>automation</category>
    </item>
    <item>
      <title>How to debug PDF files</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Fri, 21 Aug 2026 13:09:55 +0000</pubDate>
      <link>https://dev.to/idrsolutions/how-to-debug-pdf-files-n5k</link>
      <guid>https://dev.to/idrsolutions/how-to-debug-pdf-files-n5k</guid>
      <description>&lt;p&gt;The first JPedal release of 2023 has just been published and with it, some exciting new features have been added to our Java PDF debugger! With a PDF debugger, you can inspect and debug PDF files easily. Read about our new release &lt;a href="https://www.idrsolutions.com/docs/jpedal/release-notes/2023/2023-01-release-notes" rel="noopener noreferrer"&gt;here&lt;/a&gt; to find out more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing Images in the PDF debugger
&lt;/h2&gt;

&lt;p&gt;You can now view images in JPedal’s own PDF debugger.&lt;/p&gt;

&lt;p&gt;The Xref Viewer and the Object Tree Viewer both allow you to view the image content of XObjects. This can be done by selecting an XObject and pressing ‘Show Image’.&lt;/p&gt;

&lt;p&gt;The Command Window allows you to view the image content of ID and DO commands. This can be done by right-clicking on the command and pressing ‘View Image’.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8m0yit4ttulgvxuw9wjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8m0yit4ttulgvxuw9wjd.png" alt="JPedal PDF Inspector" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more about viewing images in the inspector &lt;a href="https://www.idrsolutions.com/docs/jpedal/tutorials/viewer/inspect-the-contents-of-pdf-files-with-the-inspector#view-images" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debug Breakpoints
&lt;/h2&gt;

&lt;p&gt;The Limit Decode Slider in the PDF debugger now has breakpoints.&lt;/p&gt;

&lt;p&gt;You can select a command to toggle a breakpoint and pressing the resume button will decode the page up until the next breakpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnhn8qvgfhqbobvmfku4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnhn8qvgfhqbobvmfku4r.png" alt="Breakpoints JPedal PDF Inspector" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more about breakpoints &lt;a href="https://www.idrsolutions.com/docs/jpedal/tutorials/viewer/inspect-the-contents-of-pdf-files-with-the-inspector#pause-decoding-at-a-specific-command" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xref Viewer Improvements
&lt;/h2&gt;

&lt;p&gt;The Xref Viewer has been updated and now supports cross-reference streams as well as Xref tables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff76kdkbls9y8fbkdk79m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff76kdkbls9y8fbkdk79m.png" alt="Xref Viewer JPedal PDF Inspector" width="750" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more about the Xref Viewer &lt;a href="https://www.idrsolutions.com/docs/jpedal/tutorials/viewer/inspect-the-contents-of-pdf-files-with-the-inspector#view-the-cross-references" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;You can read more about JPedal’s PDF inspector &lt;a href="https://www.idrsolutions.com/jpedal/pdf-inspector" rel="noopener noreferrer"&gt;on our website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>PDF Performance and UX Issues in Web Publishing (Why PDFs Slow Down Websites)</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Wed, 19 Aug 2026 08:50:56 +0000</pubDate>
      <link>https://dev.to/idrsolutions/pdf-performance-and-ux-issues-in-web-publishing-why-pdfs-slow-down-websites-53h2</link>
      <guid>https://dev.to/idrsolutions/pdf-performance-and-ux-issues-in-web-publishing-why-pdfs-slow-down-websites-53h2</guid>
      <description>&lt;h2&gt;
  
  
  Why PDFs Cause Performance and UX Issues in Web Publishing
&lt;/h2&gt;

&lt;p&gt;Embedding PDFs in websites is a common approach for digital publishing platforms, but it often introduces performance and user experience issues that are difficult to control.&lt;/p&gt;

&lt;p&gt;If you manage a publishing platform, content hub, or document-heavy application, you have likely seen slow load times, poor mobile usability, and limited flexibility when working with PDFs in the browser.&lt;/p&gt;

&lt;p&gt;Understanding why PDFs struggle in web environments is key to improving both content performance and user engagement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do PDFs Load Slowly on Websites?
&lt;/h2&gt;

&lt;p&gt;PDFs load slowly on websites because they are large, fixed layout files that require full document rendering in the browser. Unlike HTML, which loads progressively, PDFs often need to be processed in full before users can interact with them. This increases load times, especially for image-heavy or long documents, and impacts performance across devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PDFs Slow Down Websites (PDF Performance Issues)
&lt;/h2&gt;

&lt;p&gt;PDFs are typically large, high-fidelity files designed to preserve layout and visual accuracy. While this is useful for print and distribution, it creates performance challenges when delivered through a browser.&lt;/p&gt;

&lt;p&gt;Rendering a PDF requires significant browser resources. Instead of loading lightweight, structured web content, the browser must process an entire document, often including high-resolution images and complex formatting.&lt;/p&gt;

&lt;p&gt;For publishing platforms, this results in slower page load times, delayed interaction, and inconsistent rendering across devices. As content libraries scale, these performance issues compound, impacting overall site speed and increasing bounce rates.&lt;/p&gt;

&lt;p&gt;The impact is even more pronounced on mobile, where bandwidth and processing power are limited, and users expect fast, responsive experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  PDF User Experience Problems (Mobile and Responsive Issues)
&lt;/h2&gt;

&lt;p&gt;PDFs are not designed to be responsive. On mobile devices, users often need to zoom, pan, and manually navigate documents just to read basic content.&lt;/p&gt;

&lt;p&gt;This creates friction compared to native web pages, where content automatically adapts to screen size and supports intuitive scrolling and interaction.&lt;/p&gt;

&lt;p&gt;For publishers, this directly affects engagement metrics. When users struggle to consume content, they are more likely to drop off, reducing time on page and overall retention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PDFs Don’t Work Well on Websites
&lt;/h2&gt;

&lt;p&gt;At a fundamental level, PDFs were built for print, not for the web. They are fixed-layout documents, whereas modern web experiences rely on flexible, responsive, and interactive content.&lt;/p&gt;

&lt;p&gt;When PDFs are embedded into websites, they rely on browser-based rendering engines that limit performance, control, and consistency. This makes it difficult for publishing teams to optimise content delivery, personalise experiences, or integrate seamlessly with web analytics and workflows.&lt;/p&gt;

&lt;p&gt;As a result, PDFs often become a constraint rather than an enabler in digital publishing environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Alternatives to PDFs for Web Publishing
&lt;/h2&gt;

&lt;p&gt;To address these challenges, many publishing platforms are moving towards web-native formats such as HTML5 and SVG.&lt;/p&gt;

&lt;p&gt;By converting PDFs into HTML5 content, publishers can deliver faster load times, responsive layouts, and a more seamless reading experience across devices.&lt;/p&gt;

&lt;p&gt;This approach also provides greater control over content structure, styling, and interaction, making it easier to optimise performance, improve accessibility, and integrate with existing web systems.&lt;/p&gt;

&lt;p&gt;For publishing teams managing large volumes of content, this shift enables better scalability and a more consistent user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Fix PDF Performance and UX Issues in Web Publishing
&lt;/h2&gt;

&lt;p&gt;PDFs remain useful for document distribution, but they introduce clear limitations when used within web publishing platforms.&lt;/p&gt;

&lt;p&gt;If performance, responsiveness, and user engagement are priorities, relying on embedded PDFs can hold your platform back.&lt;/p&gt;

&lt;p&gt;Converting PDFs into web-native formats offers a more scalable and user-friendly solution. Tools like BuildVu enable publishing teams to transform PDFs into fast, responsive HTML5 content that works seamlessly in the browser.&lt;/p&gt;

&lt;p&gt;By making this shift, publishing platforms can reduce friction, improve load times, and create a better experience for their users.&lt;/p&gt;

&lt;p&gt;Explore more ways to improve digital publishing performance, user experience, and content delivery at scale. &lt;a href="https://www.idrsolutions.com/buildvu/?mtm_campaign=PublishingICP" rel="noopener noreferrer"&gt;Trial BuildVu now&lt;/a&gt; to convert your PDFs into fast, web-native HTML5 content.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>html</category>
      <category>pdf</category>
    </item>
    <item>
      <title>Comparing TIFF Compression Algorithms</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Fri, 14 Aug 2026 12:47:38 +0000</pubDate>
      <link>https://dev.to/idrsolutions/comparing-tiff-compression-algorithms-32an</link>
      <guid>https://dev.to/idrsolutions/comparing-tiff-compression-algorithms-32an</guid>
      <description>&lt;p&gt;In this post, we will be exploring the different TIFF compression techniques you can use. We will investigate their effect on different metrics such as file size, quality of output, and speed. We will be using our image library JDeli to compress a TIFF file (sample image). &lt;a href="https://www.idrsolutions.com/jdeli/" rel="noopener noreferrer"&gt;JDeli&lt;/a&gt; is the best pure Java image library for performance and efficiency.&lt;/p&gt;

&lt;p&gt;For the baseline of our comparisons, we will use the following uncompressed image. It has a file size of 39.3MB. It takes just under 5 seconds to encode.&lt;/p&gt;

&lt;h2&gt;
  
  
  JPEG
&lt;/h2&gt;

&lt;p&gt;First introduced in the 90s, JPEG has remained a popular compression format for images due to its decent tradeoff between quality and file size. JPEG is lossy meaning you cannot recover the original pixel data from the compressed image.&lt;/p&gt;

&lt;p&gt;Straight off the bat, we see a dramatic reduction in file size: 1.2MB! Even with this tiny file size, the quality of the image is only slightly worse than the original. &lt;/p&gt;

&lt;p&gt;Viewing at its default resolution, it is hard to tell the difference, however upon zooming in you will notice a less sharp image with slightly more noise and artefacts. Using JPEG compression, the encoding takes around 5 seconds, it is almost as quick as the original.&lt;/p&gt;

&lt;h2&gt;
  
  
  LZW
&lt;/h2&gt;

&lt;p&gt;Lempel–Ziv–Welch (named after its creators) was introduced in 1984, and is used today by Unix’s compress program. It is also the compression algorithm used in GIF images.&lt;/p&gt;

&lt;p&gt;Using LZW compression, we observe a file size of 18MB. Since LZW is lossless, there is no reduction in the quality of the image. Like JPEG, encoding with LZW takes around 5 seconds.&lt;/p&gt;

&lt;p&gt;An interesting quirk about LZW is that is has the potential to make file sizes bigger. An image with lots of noise will not see a reduced file size if compressed with LZW.&lt;/p&gt;

&lt;h2&gt;
  
  
  DEFLATE
&lt;/h2&gt;

&lt;p&gt;DEFLATE was also designed in the 90s and is popular in PNG images and also the ZIP archive format.&lt;/p&gt;

&lt;p&gt;Using DEFLATE, the file size is reduced. Like LZW, DEFLATE is lossless, so the quality of the compressed image remains the same as the original. The downside of DEFLATE however, is that it takes much longer to encode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, there is no best tiff compression algorithm that solves all problems. JPEG is best if you want a tiny file size with a small reduction in quality however LZW and DEFLATE are necessary if you want to preserve the original image. LZW encodes slightly larger than DEFLATE but is much faster so the answer will depend on your use case.&lt;/p&gt;

&lt;p&gt;As experienced Java developers, we help you &lt;a href="https://blog.idrsolutions.com/working-with-images-in-java/" rel="noopener noreferrer"&gt;work with images in Java&lt;/a&gt; and bring over a decade of hands-on experience with many image file formats.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to find PDF page size in Java (Tutorial)</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Wed, 12 Aug 2026 10:00:48 +0000</pubDate>
      <link>https://dev.to/idrsolutions/how-to-find-pdf-page-size-in-java-tutorial-1n93</link>
      <guid>https://dev.to/idrsolutions/how-to-find-pdf-page-size-in-java-tutorial-1n93</guid>
      <description>&lt;p&gt;PDF files are not directly supported by Java. This tutorial shows you how to extract PDF page size (height and width) from a PDF file in simple steps using the &lt;a href="https://www.idrsolutions.com/jpedal/" rel="noopener noreferrer"&gt;JPedal Java PDF library&lt;/a&gt;. JPedal is the best Java PDF library for developers. The page size can be defined in Centimetres, Inches and pixels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use a third-party library to handle PDF files?
&lt;/h2&gt;

&lt;p&gt;PDF files are a very complex binary/text hybrid data structure which is a subset of the even more complicated Postscript format. In this example, we will use our &lt;a href="https://www.idrsolutions.com/jpedal/" rel="noopener noreferrer"&gt;JPedal&lt;/a&gt; Java PDF library to make this task simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to find PDF page size in Java
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add JPedal to your class or module path. (download the &lt;a href="https://www.idrsolutions.com/jpedal/#why-buy" rel="noopener noreferrer"&gt;trial jar&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Create a File handle, InputStream, or URL pointing to the PDF file&lt;/li&gt;
&lt;li&gt;Include a password if file password protected&lt;/li&gt;
&lt;li&gt;Open the PDF file&lt;/li&gt;
&lt;li&gt;Extract the data for each page&lt;/li&gt;
&lt;li&gt;Close the PDF file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  and the Java code to find PDF Page size…
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PdfUtilities&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PdfUtilities&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//if needed&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pageCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPageCount&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pageCount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openPDFFile&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;pageDimensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPageDimensions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pageNum&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;PageUnits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Inches&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;PageSizeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CropBox&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closePDFfile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Blog post explaining how &lt;a href="https://blog.idrsolutions.com/what-is-pdf-pagesize/" rel="noopener noreferrer"&gt;MediaBox and CropBox define a PDF page size&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Javadoc link to &lt;a href="https://files.idrsolutions.com/maven/site/jpedal/apidocs/org/jpedal/examples/PdfUtilities.PageSizeType.html" rel="noopener noreferrer"&gt;PageSizeType class&lt;/a&gt; which defines whether to use MediaBox or CropBox (if in doubt use CropBox)&lt;/li&gt;
&lt;li&gt;Javadoc link to &lt;a href="https://files.idrsolutions.com/maven/site/jpedal/apidocs/org/jpedal/examples/PdfUtilities.PageUnits.html" rel="noopener noreferrer"&gt;PageUnits class&lt;/a&gt; which defines sizes&lt;/li&gt;
&lt;li&gt;Javadoc link to &lt;a href="https://files.idrsolutions.com/maven/site/jpedal/apidocs/org/jpedal/examples/PdfUtilities.html" rel="noopener noreferrer"&gt;PageUtilities class&lt;/a&gt; which documents this Utility class&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>pdf</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Measure content performance with Analytics – Why convert PDF magazines to HTML5?</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Fri, 07 Aug 2026 13:22:43 +0000</pubDate>
      <link>https://dev.to/idrsolutions/measure-content-performance-with-analytics-why-convert-pdf-magazines-to-html5-h4d</link>
      <guid>https://dev.to/idrsolutions/measure-content-performance-with-analytics-why-convert-pdf-magazines-to-html5-h4d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8khvat06o2s8z3a2bl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8khvat06o2s8z3a2bl9.png" alt="Analytics Dashboard" width="799" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the things that all good content producers rely heavily on is analytics. Analytics give you the opportunity to see what is doing well (the stuff you need to do more of), and what isn’t doing well (the stuff you need to do less of).&lt;/p&gt;

&lt;p&gt;Not only do they let you know about the performance of your content, but they can also give you information about the people consuming your content. For example, there is a 7.28% chance that you are reading this from Germany (shout out to our German readers!). This allows you to tailor your content to your demographics and to bring in better quality traffic.&lt;/p&gt;

&lt;p&gt;For those of you advertising to your readers, you can also increase your ad revenue by targeting your readers with adverts that you know are most relevant to them. For example there are companies that pay Facebook good money to display their dating website advert to the users who have recently set their relationship status to Single.&lt;/p&gt;

&lt;p&gt;Unfortunately this is something that PDF is completely lacking, but by converting to HTML5 you can enable this functionality, and start measuring your content and demographics!&lt;/p&gt;

&lt;p&gt;You can use our &lt;a href="https://www.idrsolutions.com/online-pdf-to-html5-converter/" rel="noopener noreferrer"&gt;online converter&lt;/a&gt; to test the PDF conversion to HTML. Try out some sample copies and start tracking right away!&lt;/p&gt;

&lt;p&gt;This article is part of a series where we talk about the advantages of publishing your PDF magazines online as HTML5. &lt;a href="https://blog.idrsolutions.com/why-convert-pdf-magazines-to-html5-series-index/" rel="noopener noreferrer"&gt;Click here&lt;/a&gt; to see more advantages.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>html</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Java CMYK to RGB Conversion – Speed Comparison</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Thu, 06 Aug 2026 14:03:12 +0000</pubDate>
      <link>https://dev.to/idrsolutions/java-cmyk-to-rgb-conversion-speed-comparison-1onl</link>
      <guid>https://dev.to/idrsolutions/java-cmyk-to-rgb-conversion-speed-comparison-1onl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Some optimisations are best left to Java. For example a &lt;code&gt;System.arraycopy&lt;/code&gt; is the fastest way to create a new version because it is optimised in hardware inside Java. So in general, any function which might have hardware optimisation is best left to the JVM.&lt;/p&gt;

&lt;p&gt;So what about image data conversion? Is it better to delegate it to Java or Do It Yourself? I have been looking at a file which was slow to decode. The bottleneck turned out to be the CMYK to RGB conversion so I decided to have a look…&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 1: Using ColorConvertOp
&lt;/h2&gt;

&lt;p&gt;My original code used a ColorConvertOp to do the image conversion on the raw CMYK data and then create an RGB image with the converted data. Here is the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;bands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="cm"&gt;/**turn it into a BufferedImage so we can filter*/&lt;/span&gt;&lt;span class="nc"&gt;DataBuffer&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DataBufferByte&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/**create RGB colorspace and model*/&lt;/span&gt;&lt;span class="nc"&gt;ColorSpace&lt;/span&gt; &lt;span class="n"&gt;rgbCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;GenericColorSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getColorSpaceInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="cm"&gt;/**define the conversion. hints can be replaced with null*/&lt;/span&gt;&lt;span class="nc"&gt;ColorConvertOp&lt;/span&gt; &lt;span class="nc"&gt;CSToRGB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ColorConvertOp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
   &lt;span class="nc"&gt;DeviceCMYKColorSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getColorSpaceInstance&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;rgbCS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
   &lt;span class="nc"&gt;ColorSpaces&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hints&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/**create RGB colorspace and model*/&lt;/span&gt;&lt;span class="nc"&gt;ComponentColorModel&lt;/span&gt; &lt;span class="n"&gt;rgbModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ComponentColorModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;rgbCS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ColorModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OPAQUE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
   &lt;span class="nc"&gt;DataBuffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE_BYTE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferedImage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;BufferedImage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE_INT_RGB&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;WritableRaster&lt;/span&gt; &lt;span class="n"&gt;rgbRaster&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rgbModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;createCompatibleWritableRaster&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;CSToRGB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Raster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createInterleavedRaster&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bands&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;rgbRaster&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgbRaster&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the sample page it takes 73 seconds on my fast Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 2: Manual Pixel Conversion
&lt;/h2&gt;

&lt;p&gt;Version 2 does the pixel conversion manually and then builds the image from that. A major advantage of this is that I can add optimisations. In this case I cache the last value so I only need to do the conversion if the value changes – on an empty page of 10,000 white pixels, I will get a massive boost as I only need to convert the value once and reuse it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ColorSpace&lt;/span&gt; &lt;span class="no"&gt;CMYK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;DeviceCMYKColorSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getColorSpaceInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;BufferedImage&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;new_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pixelCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;lastC&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lastM&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lastY&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lastK&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Y&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;span class="cm"&gt;/**
* loop through each pixel changing CMYK values to RGB
*/&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pixelReached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;pixelCount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="no"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="o"&gt;)/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="no"&gt;M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="o"&gt;)/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="no"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="o"&gt;)/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="no"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="o"&gt;)/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastC&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="no"&gt;C&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;lastM&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;lastY&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="no"&gt;Y&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;lastK&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
&lt;span class="c1"&gt;//use existing values if not changed&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;//work out new&lt;/span&gt;
&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;CMYK&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toRGB&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]{&lt;/span&gt;&lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;Y&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;//cache values&lt;/span&gt;
&lt;span class="n"&gt;lastC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;lastM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;lastY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;lastK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pixelReached&lt;/span&gt;&lt;span class="o"&gt;++]=(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pixelReached&lt;/span&gt;&lt;span class="o"&gt;++]=(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pixelReached&lt;/span&gt;&lt;span class="o"&gt;++]=(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="cm"&gt;/**
* turn data into RGB image
*/&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferedImage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;BufferedImage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TYPE_INT_RGB&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Raster&lt;/span&gt; &lt;span class="n"&gt;raster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createInterleavedRaster&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raster&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Comparison
&lt;/h2&gt;

&lt;p&gt;The method is longer, but what is the speed difference? On my Mac this takes an astonishing 11 seconds! My next task is to see whether it is the same on other platforms…&lt;/p&gt;

&lt;p&gt;I’ve kept the old code (in the hope Oracle one day optimises the filter function), but for the moment you can guess which version I am using…&lt;/p&gt;

&lt;p&gt;Have you found any similar cases where a DIY approach is much faster?&lt;/p&gt;

&lt;p&gt;As experienced Java developers, we help you &lt;a href="https://blog.idrsolutions.com/working-with-images-in-java/" rel="noopener noreferrer"&gt;work with images in Java&lt;/a&gt; and bring over a decade of hands-on experience with many image file formats.&lt;/p&gt;

</description>
      <category>java</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to search a PDF file in Java (Tutorial)</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Wed, 05 Aug 2026 13:38:29 +0000</pubDate>
      <link>https://dev.to/idrsolutions/how-to-search-a-pdf-file-in-java-tutorial-5h3f</link>
      <guid>https://dev.to/idrsolutions/how-to-search-a-pdf-file-in-java-tutorial-5h3f</guid>
      <description>&lt;p&gt;This tutorial shows you how to find words in a PDF file in simple steps using the &lt;a href="https://www.idrsolutions.com/jpedal/" rel="noopener noreferrer"&gt;JPedal&lt;/a&gt; Java PDF library. JPedal is the best Java PDF library for developers. It includes a PDF search engine that provides an easy-to-use Java PDF API to find words and phrases in a PDF document.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to search PDF file in Java
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.idrsolutions.com/jpedal/#why-buy" rel="noopener noreferrer"&gt;Download&lt;/a&gt; JPedal trial jar.&lt;/li&gt;
&lt;li&gt;Create a File handle, InputStream or URL pointing to the PDF file&lt;/li&gt;
&lt;li&gt;Include a password if file password protected&lt;/li&gt;
&lt;li&gt;Open the PDF file&lt;/li&gt;
&lt;li&gt;Scan the pages&lt;/li&gt;
&lt;li&gt;Close the PDF file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  and the Java code to search a PDF…
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/document.pdf"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;FindTextInRectangle&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FindTextInRectangle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;//extract.setPassword("password");&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openPDFFile&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pageCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPageCount&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pageCount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;coords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findTextOnPage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"textToFind"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;SearchType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MUTLI_LINE_RESULTS&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closePDFfile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why can’t I just search the PDF file directly?
&lt;/h2&gt;

&lt;p&gt;You cannot simply search inside a PDF file because the text data is stored in a special binary format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related tutorials
&lt;/h2&gt;

&lt;p&gt;If you are looking to search PDF files in JPedal, we recommend you start with this tutorials:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.idrsolutions.com/docs/jpedal/tutorials/search/find-text-in-a-pdf-file" rel="noopener noreferrer"&gt;How to Find Text in a PDF File using Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>pdf</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>iOS and HTML5: Gotcha with Absolute Positioning</title>
      <dc:creator>IDRSolutions</dc:creator>
      <pubDate>Wed, 29 Jul 2026 08:52:21 +0000</pubDate>
      <link>https://dev.to/idrsolutions/ios-and-html5-gotcha-with-absolute-positioning-2gla</link>
      <guid>https://dev.to/idrsolutions/ios-and-html5-gotcha-with-absolute-positioning-2gla</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One of the aims of &lt;a href="https://www.idrsolutions.com/buildvu/" rel="noopener noreferrer"&gt;BuildVu&lt;/a&gt; and all of its various view modes (all 9 of them) was to make viewing of PDF files easy and platform-independent, where the user only needs a relatively modern web browser to view them.&lt;/p&gt;

&lt;p&gt;And as we designed the output to be used by the browser, we also allow you to select and search the text using your browser’s default tools, and this free functionality normally works great in all web browsers, across all platforms, even Android devices, as you can see in the images in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue on iOS Browsers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3zczqqw1jhxmlrf4xtmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3zczqqw1jhxmlrf4xtmy.png" alt="ios browser screen grab" width="800" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, this sadly isn’t true within Apple’s current version of Safari on iOS and Chrome on iOS. Currently, both don’t quite support all the latest CSS to as great a degree as other mobile devices, and as a result of its bizarre Selection engine, it’s very difficult and often impossible to select text on pages containing complicated CSS (explained below).&lt;/p&gt;

&lt;p&gt;We recently had a customer query us about why they couldn’t select the text of our output on their iPad, which struck us as an odd question; the default mode for our output has had selectable text for as long as I can recall so my initial thought was that it may have just been a user unfamiliar with how to select text on an iPad. However, we still checked to be sure and were surprised to find that the text wasn’t selectable.&lt;/p&gt;

&lt;p&gt;This was puzzling because, as I mentioned before, the text has always been selectable, it is, after all, just text within a div tag in the HTML, and we were sure it worked previously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hq27qw36ydhxi2hk19j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hq27qw36ydhxi2hk19j.png" alt="ios browser screenshot" width="800" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Investigating the Problem
&lt;/h2&gt;

&lt;p&gt;After going over our current output, I found some older output that worked and had a look at the differences to the current version.&lt;/p&gt;

&lt;p&gt;Visually they looked almost identical, with a few improvements in regard to character spacing in our current version and a different background colour.&lt;/p&gt;

&lt;p&gt;Structurally, the newer version differs quite a lot from the older version. In our older versions, we placed the text within div tags under our parent jpedal tag with styling like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body style="background-color: rgb(55,55,65);"&amp;gt;
&amp;lt;div id="jpedal" style="position:relative; width: 984px; margin: 0 auto;"&amp;gt;
&amp;lt;!– Shared CSS values –&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
.t {
position:absolute;
white-space:nowrap;
overflow:visible;
z-index:1;
}
.tr {
-webkit-transform-origin: left top;
-ms-transform-origin: left top;
-moz-transform-origin: left top;
-o-transform-origin: left top;
}
&amp;lt;/style&amp;gt;
&amp;lt;!– Inline CSS values –&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
#t1_1 {
left:90px;
top:60px;
FONT-SIZE: 60px;
FONT-FAMILY: CataneoBT-Regular1;
color:rgb(0,85,149);
}
#t2_1 {
-webkit-transform:matrix(0.97,0,-0.2,0.97,114, 181);
-ms-transform:matrix(0.97,0,-0.2,0.97,114, 181);
-moz-transform:matrix(0.97,0,-0.2,0.97,114, 181);
-o-transform:matrix(0.97,0,-0.2,0.97,114, 181);
FONT-SIZE: 21px;
FONT-FAMILY: IGNACK-RaleighBT-Roman1;
color:rgb(35,32,32);
}
#t3_1 {
-webkit-transform:matrix(0.97,0,-0.2,0.97,350, 212);
-ms-transform:matrix(0.97,0,-0.2,0.97,350, 212);
-moz-transform:matrix(0.97,0,-0.2,0.97,350, 212);
-o-transform:matrix(0.97,0,-0.2,0.97,350, 212);
FONT-SIZE: 13px;
FONT-FAMILY: IGNACK-RaleighBT-Roman1;
color:rgb(35,32,32);
}
&amp;lt;/style&amp;gt;
&amp;lt;!– Any embedded fonts defined here –&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
@font-face {
font-family: CataneoBT-Regular1;
src: url("01/fonts/CataneoBT-Regular.woff");
}
@font-face {
font-family: IGNACK-RaleighBT-Roman1;
src: url("01/fonts/IGNACK-RaleighBT-Roman.woff");
}
&amp;lt;/style&amp;gt;
&amp;lt;!– Text defined here and setup in CSS –&amp;gt;
&amp;lt;div id="t1_1″ class="t"&amp;gt;Some things never change&amp;lt;/div&amp;gt;
&amp;lt;div id="t2_1″ class="t tr"&amp;gt;Never trust a dog to watch your food.&amp;lt;/div&amp;gt;
&amp;lt;div id="t3_1″ class="t tr"&amp;gt;â��&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqwx6hve3n4k6mida5nv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqwx6hve3n4k6mida5nv.png" alt="ios browser text selection" width="800" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We simply apply the correct styling and letter spacing to each element via its class and ID attributes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction of Parent Divs
&lt;/h2&gt;

&lt;p&gt;To reduce the large amount of class=”t”, which is a CSS class in our older output that contained some CSS rules common to all of our text and other repeated values in the CSS for each div’s ID, we introduced several parent divs that reduce file size and make our CSS easier to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of Current Output
&lt;/h2&gt;

&lt;p&gt;Below you can see an example of the current output and it’s structure (Note: As with the previous example, this is just a snippet of the relevant parts of our output):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body style="background-color:#919191;"&amp;gt;
&amp;lt;div id="jpedal" style="position:relative; width: 984px; height: 1179px; overflow: hidden; margin: 0 auto; box-shadow: 0 2px 6px rgba(100, 100, 100, 0.5);"&amp;gt;
&amp;lt;!– Begin shared CSS values –&amp;gt;
&amp;lt;!–[if lt IE 9]&amp;gt;&amp;lt;style type="text/css"&amp;gt;.text div div{zoom: 25%;}&amp;lt;/style&amp;gt;&amp;lt;![endif]–&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
.text {
position: absolute;
-webkit-transform-origin: top left;
-moz-transform-origin: top left;
-o-transform-origin: top left;
-ms-transform-origin: top left;
-webkit-transform: scale(0.25);
-moz-transform: scale(0.25);
-o-transform: scale(0.25);
-ms-transform: scale(0.25);
z-index: 1;
}
.text div div {
position:absolute;
white-space:nowrap;
overflow:visible;
}
&amp;lt;/style&amp;gt;
&amp;lt;!– End shared CSS values –&amp;gt;
&amp;lt;!– Begin inline CSS –&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
#t1_1{left:360px;top:240px;}
#t2_1{-webkit-transform:matrix(0.97,0,-0.2,0.97,456, 724);-ms-transform:matrix(0.97,0,-0.2,0.97,456, 724);-moz-transform:matrix(0.97,0,-0.2,0.97,456, 724);-o-transform:matrix(0.97,0,-0.2,0.97,456, 724);}
#t3_1{-webkit-transform:matrix(0.97,0,-0.2,0.97,1400, 848);-ms-transform:matrix(0.97,0,-0.2,0.97,1400, 848);-moz-transform:matrix(0.97,0,-0.2,0.97,1400, 848);-o-transform:matrix(0.97,0,-0.2,0.97,1400, 848);}
#t4_1{left:1456px;top:848px;}
#t2_1,#t3_1 {
-webkit-transform-origin: left top;
-ms-transform-origin: left top;
-moz-transform-origin: left top;
-o-transform-origin: left top;
}
.s2_1{
FONT-SIZE: 84px;
FONT-FAMILY: IGNACK-RaleighBT-Roman1;
color: rgb(35,32,32);
}
.s1_1{
FONT-SIZE: 240px;
FONT-FAMILY: CataneoBT-Regular1;
color: rgb(0,85,149);
}
.s3_1{
FONT-SIZE: 52px;
FONT-FAMILY: IGNACK-RaleighBT-Roman1;
color: rgb(35,32,32);
}
&amp;lt;/style&amp;gt;
&amp;lt;!– End inline CSS –&amp;gt;
&amp;lt;!– Begin embedded font definitions –&amp;gt;
&amp;lt;style type="text/css" &amp;gt;
@font-face {
font-family: CataneoBT-Regular1;
src: url("index/fonts/CataneoBT-Regular.woff");
}
@font-face {
font-family: IGNACK-RaleighBT-Roman1;
src: url("index/fonts/IGNACK-RaleighBT-Roman.woff");
}
&amp;lt;/style&amp;gt;
&amp;lt;!– End embedded font definitions –&amp;gt;
&amp;lt;!– Begin text definitions (Positioned/styled in CSS) –&amp;gt;
&amp;lt;div class="text"&amp;gt;
&amp;lt;div class="s1_1″&amp;gt;
&amp;lt;div id="t1_1″&amp;gt;Some things never change&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class="s2_1″&amp;gt;
&amp;lt;div id="t2_1″&amp;gt;Never trust a dog to watch your food.&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class="s3_1″&amp;gt;
&amp;lt;div id="t3_1″&amp;gt;â��&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fluk68lnp17xwq5lsshyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fluk68lnp17xwq5lsshyn.png" alt="ios browser screenshot" width="800" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This reduced our output length by a lot; not having to output the font-family per ID and the class=”t” per element adds up to a lot of saved characters in the output files, which consequently makes large converted files with a lot of similar text smaller.&lt;/p&gt;

&lt;p&gt;However, nesting these absolutely positioned elements appears to be what the issue is in iOS. This probably isn’t intended behaviour and may well be a bug with iOS!&lt;/p&gt;

&lt;h2&gt;
  
  
  Workaround and Conclusion
&lt;/h2&gt;

&lt;p&gt;One solution we’ve come up with for this is to change the output on the page when navigated to in iOS to something it can select the text of. Of course, this affects the performance of our output when looked at on iOS devices, which isn’t the best compromise.&lt;/p&gt;

&lt;p&gt;My personal hope is that this issue is rectified within iOS itself so that other developers don’t have to encounter this oddity.&lt;/p&gt;

&lt;p&gt;Have you had any difficulties with selecting text on iOS or other web browsers? We’d love to hear about them and how you solved them!&lt;/p&gt;

</description>
      <category>ios</category>
      <category>html</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
