SDL_image: Added pitch parameter for images that have aligned pixel rows

From 2cd10196d4a3868797d25b7ba41dfbd85e53bb4f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 23 May 2022 12:34:59 -0700
Subject: [PATCH] Added pitch parameter for images that have aligned pixel rows

Fixes https://github.com/libsdl-org/SDL_image/issues/256
---
 IMG_jpg.c   |  3 ++-
 tiny_jpeg.h | 35 +++++++++++++++++++++--------------
 2 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/IMG_jpg.c b/IMG_jpg.c
index 7db787e5..694ccb76 100644
--- a/IMG_jpg.c
+++ b/IMG_jpg.c
@@ -738,7 +738,8 @@ static int IMG_SaveJPG_RW_tinyjpeg(SDL_Surface *surface, SDL_RWops *dst, int fre
         jpeg_surface->w,
         jpeg_surface->h,
         3,
-        jpeg_surface->pixels
+        jpeg_surface->pixels,
+        jpeg_surface->pitch
     ) - 1; /* tinyjpeg returns 0 on error, 1 on success */
 
     if (jpeg_surface != surface) {
diff --git a/tiny_jpeg.h b/tiny_jpeg.h
index 30ec7dcc..a7abb3e4 100644
--- a/tiny_jpeg.h
+++ b/tiny_jpeg.h
@@ -66,7 +66,7 @@ int main()
         return EXIT_FAILURE;
     }
 
-    if ( !tje_encode_to_file("out.jpg", width, height, num_components, data) ) {
+    if ( !tje_encode_to_file("out.jpg", width, height, num_components, data, width * num_components) ) {
         fprintf(stderr, "Could not write JPEG\n");
         return EXIT_FAILURE;
     }
@@ -115,7 +115,8 @@ int tje_encode_to_file(const char* dest_path,
                        const int width,
                        const int height,
                        const int num_components,
-                       const unsigned char* src_data);
+                       const unsigned char* src_data,
+                       const int pitch);
 
 // - tje_encode_to_file_at_quality -
 //
@@ -139,7 +140,8 @@ int tje_encode_to_file_at_quality(const char* dest_path,
                                   const int width,
                                   const int height,
                                   const int num_components,
-                                  const unsigned char* src_data);
+                                  const unsigned char* src_data,
+                                  const int pitch);
 
 // - tje_encode_with_func -
 //
@@ -157,7 +159,8 @@ int tje_encode_with_func(tje_write_func* func,
                          const int width,
                          const int height,
                          const int num_components,
-                         const unsigned char* src_data);
+                         const unsigned char* src_data,
+                         const int pitch);
 
 #endif // TJE_HEADER_GUARD
 
@@ -964,7 +967,8 @@ static int tjei_encode_main(TJEState* state,
                             const unsigned char* src_data,
                             const int width,
                             const int height,
-                            const int src_num_components)
+                            const int src_num_components,
+                            const int pitch)
 {
 #if TJE_USE_FAST_DCT
     // Again, taken from classic japanese implementation.
@@ -1131,7 +1135,7 @@ static int tjei_encode_main(TJEState* state,
                 for ( off_x = 0; off_x < 8; ++off_x ) {
                     int block_index = (off_y * 8 + off_x);
 
-                    int src_index = (((y + off_y) * width) + (x + off_x)) * src_num_components;
+                    int src_index = (((y + off_y) * pitch) + ((x + off_x) * src_num_components));
 
                     int col = x + off_x;
                     int row = y + off_y;
@@ -1141,12 +1145,12 @@ static int tjei_encode_main(TJEState* state,
                     uint8_t r, g, b;
 
                     if(row >= height) {
-                        src_index -= (width * (row - height + 1)) * src_num_components;
+                        src_index -= (pitch * (row - height + 1));
                     }
                     if(col >= width) {
                         src_index -= (col - width + 1) * src_num_components;
                     }
-                    assert(src_index < width * height * src_num_components);
+                    assert(src_index < height * pitch);
 
                     r = src_data[src_index + 0];
                     g = src_data[src_index + 1];
@@ -1216,9 +1220,10 @@ int tje_encode_to_file(const char* dest_path,
                        const int width,
                        const int height,
                        const int num_components,
-                       const unsigned char* src_data)
+                       const unsigned char* src_data,
+                       const int pitch)
 {
-    int res = tje_encode_to_file_at_quality(dest_path, 3, width, height, num_components, src_data);
+    int res = tje_encode_to_file_at_quality(dest_path, 3, width, height, num_components, src_data, pitch);
     return res;
 }
 
@@ -1234,7 +1239,8 @@ int tje_encode_to_file_at_quality(const char* dest_path,
                                   const int width,
                                   const int height,
                                   const int num_components,
-                                  const unsigned char* src_data)
+                                  const unsigned char* src_data,
+                                  const int pitch)
 {
     FILE* fd = fopen(dest_path, "wb");
     if (!fd) {
@@ -1243,7 +1249,7 @@ int tje_encode_to_file_at_quality(const char* dest_path,
     }
 
     int result = tje_encode_with_func(tjei_stdlib_func, fd,
-                                      quality, width, height, num_components, src_data);
+                                      quality, width, height, num_components, src_data, pitch);
 
     result |= 0 == fclose(fd);
 
@@ -1257,7 +1263,8 @@ int tje_encode_with_func(tje_write_func* func,
                          const int width,
                          const int height,
                          const int num_components,
-                         const unsigned char* src_data)
+                         const unsigned char* src_data,
+                         const int pitch)
 {
     TJEState state = { 0 };
     TJEWriteContext wc = { 0 };
@@ -1303,7 +1310,7 @@ int tje_encode_with_func(tje_write_func* func,
 
     tjei_huff_expand(&state);
 
-    return tjei_encode_main(&state, src_data, width, height, num_components);
+    return tjei_encode_main(&state, src_data, width, height, num_components, pitch);
 }
 // ============================================================
 #endif // TJE_IMPLEMENTATION