changeset 1604:1f5d6a2f9638

JpegReader
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 01 Sep 2015 14:57:13 +0200
parents 905b4db3092b
children fd0464ce1962
files CMakeLists.txt Core/ImageFormats/JpegErrorManager.cpp Core/ImageFormats/JpegErrorManager.h Core/ImageFormats/JpegReader.cpp Core/ImageFormats/JpegReader.h Core/ImageFormats/JpegWriter.cpp Plugins/Engine/OrthancPlugins.cpp UnitTestsSources/ImageTests.cpp UnitTestsSources/VersionsTests.cpp
diffstat 9 files changed, 469 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Sep 01 13:08:41 2015 +0200
+++ b/CMakeLists.txt	Tue Sep 01 14:57:13 2015 +0200
@@ -124,7 +124,8 @@
   Core/ImageFormats/ImageAccessor.cpp
   Core/ImageFormats/ImageBuffer.cpp
   Core/ImageFormats/ImageProcessing.cpp
-  #Core/ImageFormats/JpegReader.cpp   # TODO
+  Core/ImageFormats/JpegErrorManager.cpp
+  Core/ImageFormats/JpegReader.cpp
   Core/ImageFormats/JpegWriter.cpp
   Core/ImageFormats/PngReader.cpp
   Core/ImageFormats/PngWriter.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/ImageFormats/JpegErrorManager.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -0,0 +1,69 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "../PrecompiledHeaders.h"
+#include "JpegErrorManager.h"
+
+namespace Orthanc
+{
+  namespace Internals
+  {
+    void JpegErrorManager::OutputMessage(j_common_ptr cinfo)
+    {
+      char message[JMSG_LENGTH_MAX];
+      (*cinfo->err->format_message) (cinfo, message);
+
+      JpegErrorManager* that = reinterpret_cast<JpegErrorManager*>(cinfo->err);
+      that->message = std::string(message);
+    }
+
+
+    void JpegErrorManager::ErrorExit(j_common_ptr cinfo)
+    {
+      (*cinfo->err->output_message) (cinfo);
+
+      JpegErrorManager* that = reinterpret_cast<JpegErrorManager*>(cinfo->err);
+      longjmp(that->setjmp_buffer, 1);
+    }
+      
+
+    JpegErrorManager::JpegErrorManager()
+    {
+      memset(&pub, 0, sizeof(struct jpeg_error_mgr));
+      memset(&setjmp_buffer, 0, sizeof(jmp_buf));
+
+      jpeg_std_error(&pub);
+      pub.error_exit = ErrorExit;
+      pub.output_message = OutputMessage;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/ImageFormats/JpegErrorManager.h	Tue Sep 01 14:57:13 2015 +0200
@@ -0,0 +1,74 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#pragma once
+
+#include <string.h>
+#include <stdio.h>
+#include <jpeglib.h>
+#include <setjmp.h>
+#include <string>
+
+namespace Orthanc
+{
+  namespace Internals
+  {
+    class JpegErrorManager 
+    {
+    private:
+      struct jpeg_error_mgr pub;  /* "public" fields */
+      jmp_buf setjmp_buffer;      /* for return to caller */
+      std::string message;
+
+      static void OutputMessage(j_common_ptr cinfo);
+
+      static void ErrorExit(j_common_ptr cinfo);
+
+    public:
+      JpegErrorManager();
+
+      struct jpeg_error_mgr* GetPublic()
+      {
+        return &pub;
+      }
+
+      jmp_buf& GetJumpBuffer()
+      {
+        return setjmp_buffer;
+      }
+
+      const std::string& GetMessage() const
+      {
+        return message;
+      }
+    };
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/ImageFormats/JpegReader.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -0,0 +1,189 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "../PrecompiledHeaders.h"
+#include "JpegReader.h"
+
+#include "JpegErrorManager.h"
+#include "../OrthancException.h"
+#include "../Logging.h"
+
+namespace Orthanc
+{
+  JpegReader::JpegReader()
+  {
+  }
+
+
+  static void Uncompress(struct jpeg_decompress_struct& cinfo,
+                         std::string& content,
+                         ImageAccessor& accessor)
+  {
+    jpeg_read_header(&cinfo, TRUE);
+    jpeg_start_decompress(&cinfo);
+
+    PixelFormat format;
+    if (cinfo.output_components == 1 &&
+        cinfo.out_color_space == JCS_GRAYSCALE)
+    {
+      format = PixelFormat_Grayscale8;
+    }
+    else if (cinfo.output_components == 3 &&
+             cinfo.out_color_space == JCS_RGB)
+    {
+      format = PixelFormat_RGB24;
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_NotImplemented);
+    }
+
+    unsigned int pitch = cinfo.output_width * cinfo.output_components;
+
+    /* Make a one-row-high sample array that will go away when done with image */
+    JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, pitch, 1);
+
+    try
+    {
+      content.resize(pitch * cinfo.output_height);
+    }
+    catch (...)
+    {
+      throw OrthancException(ErrorCode_NotEnoughMemory);
+    }
+
+    accessor.AssignReadOnly(format, cinfo.output_width, cinfo.output_height, pitch, 
+                            content.empty() ? NULL : content.c_str());
+
+    uint8_t* target = reinterpret_cast<uint8_t*>(&content[0]);
+    while (cinfo.output_scanline < cinfo.output_height) 
+    {
+      jpeg_read_scanlines(&cinfo, buffer, 1);
+      memcpy(target, buffer[0], pitch);
+      target += pitch;
+    }
+
+    // Everything went fine, "setjmp()" didn't get called
+
+    jpeg_finish_decompress(&cinfo);
+  }
+
+
+  void JpegReader::ReadFromFile(const char* filename)
+  {
+    FILE* fp = fopen(filename, "rb");
+    if (!fp)
+    {
+      throw OrthancException(ErrorCode_InexistentFile);
+    }
+
+    struct jpeg_decompress_struct cinfo;
+    memset(&cinfo, 0, sizeof(struct jpeg_decompress_struct));
+
+    Internals::JpegErrorManager jerr;
+    cinfo.err = jerr.GetPublic();
+    
+    if (setjmp(jerr.GetJumpBuffer())) 
+    {
+      jpeg_destroy_decompress(&cinfo);
+      fclose(fp);
+      LOG(ERROR) << "Error during JPEG encoding: " << jerr.GetMessage();
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    // Below this line, we are under the scope of a "setjmp"
+
+    jpeg_create_decompress(&cinfo);
+    jpeg_stdio_src(&cinfo, fp);
+
+    try
+    {
+      Uncompress(cinfo, content_, *this);
+    }
+    catch (OrthancException&)
+    {
+      jpeg_destroy_decompress(&cinfo);
+      fclose(fp);
+      throw;
+    }
+
+    jpeg_destroy_decompress(&cinfo);
+    fclose(fp);
+  }
+
+
+  void JpegReader::ReadFromMemory(const void* buffer,
+                                  size_t size)
+  {
+    struct jpeg_decompress_struct cinfo;
+    memset(&cinfo, 0, sizeof(struct jpeg_decompress_struct));
+
+    Internals::JpegErrorManager jerr;
+    cinfo.err = jerr.GetPublic();
+    
+    if (setjmp(jerr.GetJumpBuffer())) 
+    {
+      jpeg_destroy_decompress(&cinfo);
+      LOG(ERROR) << "Error during JPEG encoding: " << jerr.GetMessage();
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    // Below this line, we are under the scope of a "setjmp"
+    jpeg_create_decompress(&cinfo);
+    jpeg_mem_src(&cinfo, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer)), size);
+
+    try
+    {
+      Uncompress(cinfo, content_, *this);
+    }
+    catch (OrthancException&)
+    {
+      jpeg_destroy_decompress(&cinfo);
+      throw;
+    }
+
+    jpeg_destroy_decompress(&cinfo);
+  }
+
+
+  void JpegReader::ReadFromMemory(const std::string& buffer)
+  {
+    if (buffer.empty())
+    {
+      ReadFromMemory(NULL, 0);
+    }
+    else
+    {
+      ReadFromMemory(buffer.c_str(), buffer.size());
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/ImageFormats/JpegReader.h	Tue Sep 01 14:57:13 2015 +0200
@@ -0,0 +1,61 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "ImageAccessor.h"
+
+#include <string>
+
+namespace Orthanc
+{
+  class JpegReader : public ImageAccessor
+  {
+  private:
+    std::string  content_;
+
+  public:
+    JpegReader();
+
+    void ReadFromFile(const char* filename);
+
+    void ReadFromFile(const std::string& filename)
+    {
+      ReadFromFile(filename.c_str());
+    }
+
+    void ReadFromMemory(const void* buffer,
+                        size_t size);
+
+    void ReadFromMemory(const std::string& buffer);
+  };
+}
--- a/Core/ImageFormats/JpegWriter.cpp	Tue Sep 01 13:08:41 2015 +0200
+++ b/Core/ImageFormats/JpegWriter.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -30,77 +30,18 @@
  **/
 
 
+#include "../PrecompiledHeaders.h"
 #include "JpegWriter.h"
 
 #include "../OrthancException.h"
 #include "../Logging.h"
 
-#include <jpeglib.h>
-#include <setjmp.h>
-#include <stdio.h>
+#include "JpegErrorManager.h"
+
 #include <vector>
-#include <string.h>
-#include <stdlib.h>
 
 namespace Orthanc
 {
-  namespace
-  {
-    class ErrorManager 
-    {
-    private:
-      struct jpeg_error_mgr pub;  /* "public" fields */
-      jmp_buf setjmp_buffer;      /* for return to caller */
-      std::string message;
-
-      static void OutputMessage(j_common_ptr cinfo)
-      {
-        char message[JMSG_LENGTH_MAX];
-        (*cinfo->err->format_message) (cinfo, message);
-
-        ErrorManager* that = reinterpret_cast<ErrorManager*>(cinfo->err);
-        that->message = std::string(message);
-      }
-
-
-      static void ErrorExit(j_common_ptr cinfo)
-      {
-        (*cinfo->err->output_message) (cinfo);
-
-        ErrorManager* that = reinterpret_cast<ErrorManager*>(cinfo->err);
-        longjmp(that->setjmp_buffer, 1);
-      }
-      
-
-    public:
-      ErrorManager()
-      {
-        memset(&pub, 0, sizeof(struct jpeg_error_mgr));
-        memset(&setjmp_buffer, 0, sizeof(jmp_buf));
-
-        jpeg_std_error(&pub);
-        pub.error_exit = ErrorExit;
-        pub.output_message = OutputMessage;
-      }
-
-      struct jpeg_error_mgr* GetPublic()
-      {
-        return &pub;
-      }
-
-      jmp_buf& GetJumpBuffer()
-      {
-        return setjmp_buffer;
-      }
-
-      const std::string& GetMessage() const
-      {
-        return message;
-      }
-    };
-  }
-
-
   static void GetLines(std::vector<uint8_t*>& lines,
                        unsigned int height,
                        unsigned int pitch,
@@ -188,7 +129,7 @@
     struct jpeg_compress_struct cinfo;
     memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
 
-    ErrorManager jerr;
+    Internals::JpegErrorManager jerr;
     cinfo.err = jerr.GetPublic();
 
     if (setjmp(jerr.GetJumpBuffer())) 
@@ -227,7 +168,7 @@
     struct jpeg_compress_struct cinfo;
     memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
 
-    ErrorManager jerr;
+    Internals::JpegErrorManager jerr;
 
     unsigned char* data = NULL;
     unsigned long size;
--- a/Plugins/Engine/OrthancPlugins.cpp	Tue Sep 01 13:08:41 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -44,6 +44,7 @@
 #include "../../Core/Compression/GzipCompressor.h"
 #include "../../Core/ImageFormats/PngReader.h"
 #include "../../Core/ImageFormats/PngWriter.h"
+#include "../../Core/ImageFormats/JpegReader.h"
 #include "../../Core/ImageFormats/JpegWriter.h"
 
 #include <boost/regex.hpp> 
@@ -1063,22 +1064,29 @@
   {
     const _OrthancPluginUncompressImage& p = *reinterpret_cast<const _OrthancPluginUncompressImage*>(parameters);
 
+    std::auto_ptr<ImageAccessor> image;
+
     switch (p.format)
     {
       case OrthancPluginImageFormat_Png:
       {
-        std::auto_ptr<PngReader> image(new PngReader);
-        image->ReadFromMemory(p.data, p.size);
-        *(p.target) = reinterpret_cast<OrthancPluginImage*>(image.release());
-        return;
+        image.reset(new PngReader);
+        reinterpret_cast<PngReader&>(*image).ReadFromMemory(p.data, p.size);
+        break;
       }
 
       case OrthancPluginImageFormat_Jpeg:
-        // TODO
+      {
+        image.reset(new JpegReader);
+        reinterpret_cast<JpegReader&>(*image).ReadFromMemory(p.data, p.size);
+        break;
+      }
 
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
+
+    *(p.target) = reinterpret_cast<OrthancPluginImage*>(image.release());
   }
 
 
@@ -1098,8 +1106,12 @@
       }
 
       case OrthancPluginImageFormat_Jpeg:
-        // TODO
-        //writer.SetQuality(p.quality);
+      {
+        JpegWriter writer;
+        writer.SetQuality(p.quality);
+        writer.WriteToMemory(compressed, p.width, p.height, p.pitch, Convert(p.pixelFormat), p.buffer);
+        break;
+      }
 
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
--- a/UnitTestsSources/ImageTests.cpp	Tue Sep 01 13:08:41 2015 +0200
+++ b/UnitTestsSources/ImageTests.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -37,6 +37,7 @@
 #include "../Core/ImageFormats/ImageBuffer.h"
 #include "../Core/ImageFormats/PngReader.h"
 #include "../Core/ImageFormats/PngWriter.h"
+#include "../Core/ImageFormats/JpegReader.h"
 #include "../Core/ImageFormats/JpegWriter.h"
 #include "../Core/Toolbox.h"
 #include "../Core/Uuid.h"
@@ -192,21 +193,50 @@
 
 TEST(JpegWriter, Basic)
 {
-  Orthanc::ImageBuffer img(16, 16, Orthanc::PixelFormat_Grayscale8);
-  Orthanc::ImageAccessor accessor = img.GetAccessor();
-  for (unsigned int y = 0, value = 0; y < img.GetHeight(); y++)
+  std::string s;
+
   {
-    uint8_t* p = reinterpret_cast<uint8_t*>(accessor.GetRow(y));
-    for (unsigned int x = 0; x < img.GetWidth(); x++, p++)
+    Orthanc::ImageBuffer img(16, 16, Orthanc::PixelFormat_Grayscale8);
+    Orthanc::ImageAccessor accessor = img.GetAccessor();
+    for (unsigned int y = 0, value = 0; y < img.GetHeight(); y++)
     {
-      *p = value++;
+      uint8_t* p = reinterpret_cast<uint8_t*>(accessor.GetRow(y));
+      for (unsigned int x = 0; x < img.GetWidth(); x++, p++)
+      {
+        *p = value++;
+      }
+    }
+
+    Orthanc::JpegWriter w;
+    w.WriteToFile("UnitTestsResults/hello.jpg", accessor);
+
+    w.WriteToMemory(s, accessor);
+    Orthanc::Toolbox::WriteFile(s, "UnitTestsResults/hello2.jpg");
+
+    std::string t;
+    Orthanc::Toolbox::ReadFile(t, "UnitTestsResults/hello.jpg");
+    ASSERT_EQ(s.size(), t.size());
+    ASSERT_EQ(0, memcmp(s.c_str(), t.c_str(), s.size()));
+  }
+
+  {
+    Orthanc::JpegReader r1, r2;
+    r1.ReadFromFile("UnitTestsResults/hello.jpg");
+    ASSERT_EQ(16, r1.GetWidth());
+    ASSERT_EQ(16, r1.GetHeight());
+
+    r2.ReadFromMemory(s);
+    ASSERT_EQ(16, r2.GetWidth());
+    ASSERT_EQ(16, r2.GetHeight());
+
+    for (unsigned int y = 0; y < r1.GetHeight(); y++)
+    {
+      const uint8_t* p1 = reinterpret_cast<const uint8_t*>(r1.GetConstRow(y));
+      const uint8_t* p2 = reinterpret_cast<const uint8_t*>(r2.GetConstRow(y));
+      for (unsigned int x = 0; x < r1.GetWidth(); x++)
+      {
+        ASSERT_EQ(*p1, *p2);
+      }
     }
   }
-
-  Orthanc::JpegWriter w;
-  w.WriteToFile("UnitTestsResults/hello.jpg", accessor);
-
-  std::string s;
-  w.WriteToMemory(s, accessor);
-  Orthanc::Toolbox::WriteFile(s, "UnitTestsResults/hello2.jpg");
 }
--- a/UnitTestsSources/VersionsTests.cpp	Tue Sep 01 13:08:41 2015 +0200
+++ b/UnitTestsSources/VersionsTests.cpp	Tue Sep 01 14:57:13 2015 +0200
@@ -42,6 +42,7 @@
 #include <boost/version.hpp>
 #include <sqlite3.h>
 #include <lua.h>
+#include <jpeglib.h>
 
 #if ORTHANC_SSL_ENABLED == 1
 #include <openssl/opensslv.h>
@@ -116,6 +117,12 @@
   ASSERT_STREQ("1.5.12", PNG_LIBPNG_VER_STRING);
 }
 
+TEST(Versions, JpegStatic)
+{
+  ASSERT_EQ(9, JPEG_LIB_VERSION_MAJOR);
+  ASSERT_EQ(1, JPEG_LIB_VERSION_MINOR);
+}
+
 TEST(Versions, CurlSslStatic)
 {
   curl_version_info_data * vinfo = curl_version_info(CURLVERSION_NOW);