libtiff: Add support for libjpeg-turbo 2.2-dev 8/12 bit dual mode

From 0fd1a81d3547acb8f5be50bbbc3e44bde01c014b Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Fri, 25 Nov 2022 11:26:45 +0000
Subject: [PATCH] Add support for libjpeg-turbo 2.2-dev 8/12 bit dual mode

---
 CMakeLists.txt         |   6 ++-
 cmake/JPEGCodec.cmake  |  54 ++++++++++++++++------
 configure.ac           |  71 +++++++++++++++++-----------
 libtiff/CMakeLists.txt |   4 +-
 libtiff/Makefile.am    |   8 +++-
 libtiff/tif_jpeg.c     | 102 +++++++++++++++++++++++++++++++----------
 libtiff/tif_jpeg_12.c  |   6 +++
 7 files changed, 183 insertions(+), 68 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d518f004..1a982d1d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -206,7 +206,11 @@ if(JPEG_SUPPORT)
 else()
   message(STATUS "  Old JPEG support:                   Requested:${old-jpeg} Availability:${JPEG_SUPPORT} Support:${OJPEG_SUPPORT} (Depends on JPEG Support)")
 endif()
-message(STATUS "  JPEG 8/12 bit dual mode:            Requested:${jpeg12} Availability:${JPEG12_FOUND} Support:${JPEG_DUAL_MODE_8_12}")
+if(JPEG_SUPPORT AND HAVE_JPEGTURBO_DUAL_MODE_8_12)
+  message(STATUS "  JPEG 8/12 bit dual mode:            Support: yes (libjpeg turbo >= 2.2 dual mode)")
+else()
+  message(STATUS "  JPEG 8/12 bit dual mode:            Requested:${jpeg12} Availability:${JPEG12_FOUND} Support:${JPEG_DUAL_MODE_8_12}")
+endif()
 message(STATUS "  ISO JBIG support:                   Requested:${jbig} Availability:${JBIG_FOUND} Support:${JBIG_SUPPORT}")
 if(ZLIB_SUPPORT)
   message(STATUS "  LERC support:                       Requested:${lerc} Availability:${LERC_FOUND} Support:${LERC_SUPPORT}")
diff --git a/cmake/JPEGCodec.cmake b/cmake/JPEGCodec.cmake
index 5b295851..8455a3ec 100644
--- a/cmake/JPEGCodec.cmake
+++ b/cmake/JPEGCodec.cmake
@@ -39,18 +39,46 @@ if (old-jpeg AND JPEG_SUPPORT)
     set(OJPEG_SUPPORT TRUE)
 endif()
 
-# 8/12-bit jpeg mode
-set(JPEG12_INCLUDE_DIR JPEG12_INCLUDE_DIR-NOTFOUND CACHE PATH "Include directory for 12-bit libjpeg")
-set(JPEG12_LIBRARY JPEG12_LIBRARY-NOTFOUND CACHE FILEPATH "12-bit libjpeg library")
-set(JPEG_DUAL_MODE_8_12 FALSE)
-if (JPEG12_INCLUDE_DIR AND JPEG12_LIBRARY)
-    set(JPEG12_LIBRARIES ${JPEG12_LIBRARY})
-    set(JPEG12_FOUND TRUE)
-else()
-    set(JPEG12_FOUND FALSE)
+if (JPEG_SUPPORT)
+    # Check for jpeg12_read_scanlines() which has been added in libjpeg-turbo 2.2
+    # for dual 8/12 bit mode.
+    include(CheckCSourceCompiles)
+    include(CMakePushCheckState)
+    cmake_push_check_state(RESET)
+    set(CMAKE_REQUIRED_INCLUDES "${JPEG_INCLUDE_DIRS}")
+    set(CMAKE_REQUIRED_LIBRARIES "${JPEG_LIBRARIES}")
+    check_c_source_compiles(
+        "
+        #include <stddef.h>
+        #include <stdio.h>
+        #include \"jpeglib.h\"
+        int main()
+        {
+            jpeg_read_scanlines(0,0,0);
+            jpeg12_read_scanlines(0,0,0);
+            return 0;
+        }
+        "
+        HAVE_JPEGTURBO_DUAL_MODE_8_12)
+    cmake_pop_check_state()
 endif()
-option(jpeg12 "enable libjpeg 8/12-bit dual mode (requires separate 12-bit libjpeg build)" ${JPEG12_FOUND})
-if (jpeg12 AND JPEG12_FOUND)
-    set(JPEG_DUAL_MODE_8_12 TRUE)
-    set(LIBJPEG_12_PATH "${JPEG12_INCLUDE_DIR}/jpeglib.h")
+
+if (NOT HAVE_JPEGTURBO_DUAL_MODE_8_12)
+
+    # 12-bit jpeg mode in a dedicated libjpeg12 library
+    set(JPEG12_INCLUDE_DIR JPEG12_INCLUDE_DIR-NOTFOUND CACHE PATH "Include directory for 12-bit libjpeg")
+    set(JPEG12_LIBRARY JPEG12_LIBRARY-NOTFOUND CACHE FILEPATH "12-bit libjpeg library")
+    set(JPEG_DUAL_MODE_8_12 FALSE)
+    if (JPEG12_INCLUDE_DIR AND JPEG12_LIBRARY)
+        set(JPEG12_LIBRARIES ${JPEG12_LIBRARY})
+        set(JPEG12_FOUND TRUE)
+    else()
+        set(JPEG12_FOUND FALSE)
+    endif()
+    option(jpeg12 "enable libjpeg 8/12-bit dual mode (requires separate 12-bit libjpeg build)" ${JPEG12_FOUND})
+    if (jpeg12 AND JPEG12_FOUND)
+        set(JPEG_DUAL_MODE_8_12 TRUE)
+        set(LIBJPEG_12_PATH "${JPEG12_INCLUDE_DIR}/jpeglib.h")
+    endif()
+
 endif()
diff --git a/configure.ac b/configure.ac
index 1ae5573c..9833955c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -559,6 +559,7 @@ dnl Check for JPEG.
 dnl ---------------------------------------------------------------------------
 
 HAVE_JPEG=no
+HAVE_JPEGTURBO_DUAL_MODE_8_12=no
 
 AC_ARG_ENABLE(jpeg,
 	      AS_HELP_STRING([--disable-jpeg],
@@ -591,6 +592,9 @@ if test "x$enable_jpeg" != "xno" ; then
   fi
 
   if test "$jpeg_lib" = "yes" -a "$jpeg_h" = "yes" ; then
+    dnl Check for jpeg12_read_scanlines which has been added in libjpeg-turbo 2.2
+    dnl for dual 8/12 bit mode.
+    AC_CHECK_LIB(jpeg, jpeg12_read_scanlines, [HAVE_JPEGTURBO_DUAL_MODE_8_12=yes], [HAVE_JPEGTURBO_DUAL_MODE_8_12=no],)
     HAVE_JPEG=yes
   fi
 
@@ -606,9 +610,13 @@ if test "$HAVE_JPEG" = "yes" ; then
     LIBDIR="-R $with_jpeg_lib_dir $LIBDIR"
   fi
 
+  if test "$HAVE_JPEGTURBO_DUAL_MODE_8_12" = "yes"; then
+      AC_DEFINE(HAVE_JPEGTURBO_DUAL_MODE_8_12,1,[libjpeg-turbo >= 2.2 dual mode enabled])
+  fi
 fi
 
 AM_CONDITIONAL(HAVE_JPEG, test "$HAVE_JPEG" = 'yes')
+AM_CONDITIONAL(HAVE_JPEGTURBO_DUAL_MODE_8_12, test "$HAVE_JPEGTURBO_DUAL_MODE_8_12" = 'yes')
 
 dnl ---------------------------------------------------------------------------
 dnl Check for Old JPEG.
@@ -918,35 +926,38 @@ AM_CONDITIONAL(HAVE_WEBP, test "$HAVE_WEBP" = 'yes')
 
 dnl ---------------------------------------------------------------------------
 dnl Should 8/12 bit jpeg mode be enabled?
-dnl ---------------------------------------------------------------------------
-
-HAVE_JPEG12=no
-
-AC_ARG_ENABLE(jpeg12,
-	      AS_HELP_STRING([--enable-jpeg12],
-			     [enable libjpeg 8/12bit dual mode]),,)
-AC_ARG_WITH(jpeg12-include-dir,
-	    AS_HELP_STRING([--with-jpeg12-include-dir=DIR],
-			   [location of libjpeg 12bit headers]),,)
-AC_ARG_WITH(jpeg12-lib,
-	    AS_HELP_STRING([--with-jpeg12-lib=LIBRARY],
-			   [path to libjpeg 12bit library]),,)
-
-if test "x$enable_jpeg12" = "xyes" ; then
-
-  if test "x$with_jpeg12_lib" != "x" ; then
-    LIBS="$with_jpeg12_lib $LIBS"
-  fi
-  
-  HAVE_JPEG12=yes
-
-  AC_DEFINE(JPEG_DUAL_MODE_8_12,1,[8/12 bit libjpeg dual mode enabled])
-  if test "x$with_jpeg12_include_dir" != "x" ; then
-    AC_DEFINE_UNQUOTED(LIBJPEG_12_PATH,"$with_jpeg12_include_dir/jpeglib.h",[12bit libjpeg primary include file with path])
-  fi
+dnl This should not be used starting with libjpeg-turbo >= 2.2 that has
+dnl built-in support for dual mode.
+dnl ---------------------------------------------------------------------------
+
+if test "$HAVE_JPEGTURBO_DUAL_MODE_8_12" = "no"; then
+    HAVE_JPEG12=no
+
+    AC_ARG_ENABLE(jpeg12,
+              AS_HELP_STRING([--enable-jpeg12],
+                     [enable libjpeg 8/12bit dual mode (not to be used with libjpeg-turbo >= 2.2)]),,)
+    AC_ARG_WITH(jpeg12-include-dir,
+            AS_HELP_STRING([--with-jpeg12-include-dir=DIR],
+                   [location of libjpeg 12bit headers]),,)
+    AC_ARG_WITH(jpeg12-lib,
+            AS_HELP_STRING([--with-jpeg12-lib=LIBRARY],
+                   [path to libjpeg 12bit library]),,)
+
+    if test "x$enable_jpeg12" = "xyes" ; then
+
+      if test "x$with_jpeg12_lib" != "x" ; then
+        LIBS="$with_jpeg12_lib $LIBS"
+      fi
+      
+      HAVE_JPEG12=yes
+
+      AC_DEFINE(JPEG_DUAL_MODE_8_12,1,[8/12 bit libjpeg dual mode enabled])
+      if test "x$with_jpeg12_include_dir" != "x" ; then
+        AC_DEFINE_UNQUOTED(LIBJPEG_12_PATH,"$with_jpeg12_include_dir/jpeglib.h",[12bit libjpeg primary include file with path])
+      fi
+    fi
 fi
 
-
 dnl ---------------------------------------------------------------------------
 dnl Check for C++.
 dnl ---------------------------------------------------------------------------
@@ -1240,7 +1251,11 @@ LOC_MSG([  libdeflate support:                 ${HAVE_LIBDEFLATE}])
 LOC_MSG([  Pixar log-format algorithm:         ${HAVE_PIXARLOG}])
 LOC_MSG([  JPEG support:                       ${HAVE_JPEG}])
 LOC_MSG([  Old JPEG support:                   ${HAVE_OJPEG}])
-LOC_MSG([  JPEG 8/12 bit dual mode:            ${HAVE_JPEG12}])
+if test "$HAVE_JPEGTURBO_DUAL_MODE_8_12" = "yes"; then
+    LOC_MSG([  JPEG 8/12 bit dual mode:            ${HAVE_JPEGTURBO_DUAL_MODE_8_12} (libjpeg turbo >= 2.2 dual mode)])
+else
+    LOC_MSG([  JPEG 8/12 bit dual mode:            ${HAVE_JPEG12}])
+fi
 LOC_MSG([  ISO JBIG support:                   ${HAVE_JBIG}])
 LOC_MSG([  LERC support:                       ${HAVE_LERC}])
 LOC_MSG([  LZMA2 support:                      ${HAVE_LZMA}])
diff --git a/libtiff/CMakeLists.txt b/libtiff/CMakeLists.txt
index b4a15027..bde54ac3 100755
--- a/libtiff/CMakeLists.txt
+++ b/libtiff/CMakeLists.txt
@@ -121,7 +121,9 @@ endif()
 if(JPEG_SUPPORT)
   target_link_libraries(tiff PRIVATE JPEG::JPEG)
   string(APPEND tiff_requires_private " libjpeg")
-  if(JPEG_DUAL_MODE_8_12)
+  if(HAVE_JPEGTURBO_DUAL_MODE_8_12)
+    target_compile_definitions(tiff PRIVATE HAVE_JPEGTURBO_DUAL_MODE_8_12)
+  elseif(JPEG_DUAL_MODE_8_12)
     target_include_directories(tiff PRIVATE ${JPEG12_INCLUDE_DIR})
     target_link_libraries(tiff PRIVATE ${JPEG12_LIBRARIES})
   endif()
diff --git a/libtiff/Makefile.am b/libtiff/Makefile.am
index 3988da76..f5fa50f7 100644
--- a/libtiff/Makefile.am
+++ b/libtiff/Makefile.am
@@ -153,4 +153,10 @@ else
 extra_CPPFLAGS =
 endif
 
-AM_CPPFLAGS = -I$(top_srcdir)/libtiff -I$(top_srcdir)/port $(extra_CPPFLAGS)
+if HAVE_JPEGTURBO_DUAL_MODE_8_12
+JPEGTURBO_CPPFLAGS = -DHAVE_JPEGTURBO_DUAL_MODE_8_12
+else
+JPEGTURBO_CPPFLAGS =
+endif
+
+AM_CPPFLAGS = -I$(top_srcdir)/libtiff -I$(top_srcdir)/port $(extra_CPPFLAGS) $(JPEGTURBO_CPPFLAGS)
diff --git a/libtiff/tif_jpeg.c b/libtiff/tif_jpeg.c
index ed1bb58f..9eff09f5 100644
--- a/libtiff/tif_jpeg.c
+++ b/libtiff/tif_jpeg.c
@@ -124,6 +124,36 @@ typedef unsigned char boolean;
  * 16bit value?
  */
 
+/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which
+ * adds a dual-mode 8/12 bit API in the same library.
+ */
+
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
+#  define JPEG_DUAL_MODE_8_12
+/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo >= 2.2
+ * Cf https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b */
+#  undef BITS_IN_JSAMPLE
+/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */
+# if defined(FROM_TIF_JPEG_12)
+#  define BITS_IN_JSAMPLE 12
+#  define TIFF_JSAMPLE    J12SAMPLE
+#  define TIFF_JSAMPARRAY J12SAMPARRAY
+#  define TIFF_JSAMPIMAGE J12SAMPIMAGE
+#  define TIFF_JSAMPROW   J12SAMPROW
+# else
+#  define BITS_IN_JSAMPLE 8
+#  define TIFF_JSAMPLE    JSAMPLE
+#  define TIFF_JSAMPARRAY JSAMPARRAY
+#  define TIFF_JSAMPIMAGE JSAMPIMAGE
+#  define TIFF_JSAMPROW   JSAMPROW
+# endif
+#else
+# define TIFF_JSAMPLE    JSAMPLE
+# define TIFF_JSAMPARRAY JSAMPARRAY
+# define TIFF_JSAMPIMAGE JSAMPIMAGE
+# define TIFF_JSAMPROW   JSAMPROW
+#endif
+
 #if defined(JPEG_LIB_MK1)
 #define JPEG_LIB_MK1_OR_12BIT 1
 #elif BITS_IN_JSAMPLE == 12
@@ -191,7 +221,7 @@ typedef struct {
   uint16_t v_sampling;
   tmsize_t bytesperline; /* decompressed bytes per scanline */
   /* pointers to intermediate buffers when processing downsampled data */
-  JSAMPARRAY ds_buffer[MAX_COMPONENTS];
+  TIFF_JSAMPARRAY ds_buffer[MAX_COMPONENTS];
   int scancount; /* number of "scanlines" accumulated */
   int samplesperclump;
 
@@ -335,18 +365,29 @@ static int TIFFjpeg_start_compress(JPEGState *sp, boolean write_all_tables) {
   return CALLVJPEG(sp, jpeg_start_compress(&sp->cinfo.c, write_all_tables));
 }
 
-static int TIFFjpeg_write_scanlines(JPEGState *sp, JSAMPARRAY scanlines,
+static int TIFFjpeg_write_scanlines(JPEGState *sp, TIFF_JSAMPARRAY scanlines,
                                     int num_lines) {
   return CALLJPEG(sp, -1,
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12
+                  (int)jpeg12_write_scanlines(&sp->cinfo.c, scanlines,
+                                            (JDIMENSION)num_lines)
+#else
                   (int)jpeg_write_scanlines(&sp->cinfo.c, scanlines,
-                                            (JDIMENSION)num_lines));
+                                            (JDIMENSION)num_lines)
+#endif
+                 );
 }
 
-static int TIFFjpeg_write_raw_data(JPEGState *sp, JSAMPIMAGE data,
+static int TIFFjpeg_write_raw_data(JPEGState *sp, TIFF_JSAMPIMAGE data,
                                    int num_lines) {
   return CALLJPEG(
       sp, -1,
-      (int)jpeg_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines));
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12
+      (int)jpeg12_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines)
+#else
+      (int)jpeg_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines)
+#endif
+  );
 }
 
 static int TIFFjpeg_finish_compress(JPEGState *sp) {
@@ -379,18 +420,30 @@ static int TIFFjpeg_start_decompress(JPEGState *sp) {
   return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
 }
 
-static int TIFFjpeg_read_scanlines(JPEGState *sp, JSAMPARRAY scanlines,
+static int TIFFjpeg_read_scanlines(JPEGState *sp,
+                                   TIFF_JSAMPARRAY scanlines,
                                    int max_lines) {
   return CALLJPEG(
       sp, -1,
-      (int)jpeg_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION)max_lines));
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12
+      (int)jpeg12_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION)max_lines)
+#else
+      (int)jpeg_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION)max_lines)
+#endif
+  );
 }
 
-static int TIFFjpeg_read_raw_data(JPEGState *sp, JSAMPIMAGE data,
+static int TIFFjpeg_read_raw_data(JPEGState *sp,
+                                  TIFF_JSAMPIMAGE data,
                                   int max_lines) {
   return CALLJPEG(
       sp, -1,
-      (int)jpeg_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines));
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12
+      (int)jpeg12_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines)
+#else
+      (int)jpeg_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines)
+#endif
+  );
 }
 
 static int TIFFjpeg_finish_decompress(JPEGState *sp) {
@@ -637,12 +690,12 @@ static int alloc_downsampled_buffers(TIFF *tif, jpeg_component_info *comp_info,
   JPEGState *sp = JState(tif);
   int ci;
   jpeg_component_info *compptr;
-  JSAMPARRAY buf;
+  TIFF_JSAMPARRAY buf;
   int samples_per_clump = 0;
 
   for (ci = 0, compptr = comp_info; ci < num_components; ci++, compptr++) {
     samples_per_clump += compptr->h_samp_factor * compptr->v_samp_factor;
-    buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE,
+    buf = (TIFF_JSAMPARRAY)TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE,
                                 compptr->width_in_blocks * DCTSIZE,
                                 (JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
     if (buf == NULL)
@@ -1353,7 +1406,7 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
 
   /* data is expected to be read in multiples of a scanline */
   if (nrows) {
-    JSAMPROW line_work_buf = NULL;
+    TIFF_JSAMPROW line_work_buf = NULL;
 
     /*
      * For 6B, only use temporary buffer for 12 bit imagery.
@@ -1361,8 +1414,9 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
      */
     if (sp->cinfo.d.data_precision == 12) {
       line_work_buf =
-          (JSAMPROW)_TIFFmallocExt(tif, sizeof(short) * sp->cinfo.d.output_width *
-                                sp->cinfo.d.num_components);
+          (TIFF_JSAMPROW)_TIFFmallocExt(
+              tif, sizeof(short) * sp->cinfo.d.output_width *
+                                           sp->cinfo.d.num_components);
     }
 
     do {
@@ -1383,7 +1437,7 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
 
           for (iPair = 0; iPair < value_pairs; iPair++) {
             unsigned char *out_ptr = ((unsigned char *)buf) + iPair * 3;
-            JSAMPLE *in_ptr = line_work_buf + iPair * 2;
+            TIFF_JSAMPLE *in_ptr = line_work_buf + iPair * 2;
 
             out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4);
             out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) |
@@ -1502,12 +1556,12 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
         int ypos;
 
         for (ypos = 0; ypos < vsamp; ypos++) {
-          JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos];
+          TIFF_JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos];
           JDIMENSION nclump;
 #if defined(JPEG_LIB_MK1_OR_12BIT)
-          JSAMPLE *outptr = (JSAMPLE *)tmpbuf + clumpoffset;
+          TIFF_JSAMPLE *outptr = (TIFF_JSAMPLE *)tmpbuf + clumpoffset;
 #else
-          JSAMPLE *outptr = (JSAMPLE *)buf + clumpoffset;
+          TIFF_JSAMPLE *outptr = (TIFF_JSAMPLE *)buf + clumpoffset;
           if (cc <
               (tmsize_t)(clumpoffset +
                          (tmsize_t)samples_per_clump * (clumps_per_line - 1) +
@@ -2019,7 +2073,7 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s) {
 static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
   JPEGState *sp = JState(tif);
   tmsize_t nrows;
-  JSAMPROW bufptr[1];
+  TIFF_JSAMPROW bufptr[1];
   short *line16 = NULL;
   int line16_count = 0;
 
@@ -2053,7 +2107,7 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
       int value_pairs = line16_count / 2;
       int iPair;
 
-      bufptr[0] = (JSAMPROW)line16;
+      bufptr[0] = (TIFF_JSAMPROW)line16;
 
       for (iPair = 0; iPair < value_pairs; iPair++) {
         unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3;
@@ -2063,7 +2117,7 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
         out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2];
       }
     } else {
-      bufptr[0] = (JSAMPROW)buf;
+      bufptr[0] = (TIFF_JSAMPROW)buf;
     }
     if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
       return (0);
@@ -2085,8 +2139,8 @@ static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
  */
 static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
   JPEGState *sp = JState(tif);
-  JSAMPLE *inptr;
-  JSAMPLE *outptr;
+  TIFF_JSAMPLE *inptr;
+  TIFF_JSAMPLE *outptr;
   tmsize_t nrows;
   JDIMENSION clumps_per_line, nclump;
   int clumpoffset, ci, xpos, ypos;
@@ -2129,7 +2183,7 @@ static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) {
       int padding =
           (int)(compptr->width_in_blocks * DCTSIZE - clumps_per_line * hsamp);
       for (ypos = 0; ypos < vsamp; ypos++) {
-        inptr = ((JSAMPLE *)buf) + clumpoffset;
+        inptr = ((TIFF_JSAMPLE *)buf) + clumpoffset;
         outptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos];
         if (hsamp == 1) {
           /* fast path for at least Cb and Cr */
diff --git a/libtiff/tif_jpeg_12.c b/libtiff/tif_jpeg_12.c
index ac920710..29b8e914 100644
--- a/libtiff/tif_jpeg_12.c
+++ b/libtiff/tif_jpeg_12.c
@@ -1,6 +1,10 @@
 
 #include "tiffiop.h"
 
+#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
+#define JPEG_DUAL_MODE_8_12
+#endif
+
 #if defined(JPEG_DUAL_MODE_8_12)
 
 #define FROM_TIF_JPEG_12
@@ -17,7 +21,9 @@
 
 int TIFFInitJPEG_12(TIFF *tif, int scheme);
 
+#if !defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
 #include LIBJPEG_12_PATH
+#endif
 
 #include "tif_jpeg.c"