github.com/go-oss/image@v0.1.1-0.20230517025328-001b78555e78/jpeg/quality.go (about)

     1  // Copyright 2020 Takenori Nakagawa.
     2  // MIT License
     3  
     4  package jpeg
     5  
     6  import (
     7  	"image"
     8  	"io"
     9  	_ "unsafe" // for go:linkname
    10  )
    11  
    12  func isZero(arr [blockSize]int32) bool {
    13  	var zero [blockSize]int32
    14  	return arr == zero
    15  }
    16  
    17  // quality calculates Quality from DQT.
    18  // ref: https://github.com/ImageMagick/ImageMagick/blob/7.0.7.7/coders/jpeg.c#L794-L927
    19  // see LICENSE-imagemagick.
    20  func (d *decoder) quality() int32 {
    21  	var quality, qvalue, sum int32
    22  	var i, j int
    23  
    24  	for i = range d.quant {
    25  		for j = 0; j < blockSize; j++ {
    26  			sum += d.quant[i][j]
    27  		}
    28  	}
    29  
    30  	if !isZero(d.quant[0]) && !isZero(d.quant[1]) {
    31  		hash := [101]int32{
    32  			1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645,
    33  			632, 623, 613, 607, 600, 594, 589, 585, 581, 571,
    34  			555, 542, 529, 514, 494, 474, 457, 439, 424, 410,
    35  			397, 386, 373, 364, 351, 341, 334, 324, 317, 309,
    36  			299, 294, 287, 279, 274, 267, 262, 257, 251, 247,
    37  			243, 237, 232, 227, 222, 217, 213, 207, 202, 198,
    38  			192, 188, 183, 177, 173, 168, 163, 157, 153, 148,
    39  			143, 139, 132, 128, 125, 119, 115, 108, 104, 99,
    40  			94, 90, 84, 79, 74, 70, 64, 59, 55, 49,
    41  			45, 40, 34, 30, 25, 20, 15, 11, 6, 4,
    42  			0,
    43  		}
    44  		sums := [101]int32{
    45  			32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104,
    46  			27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946,
    47  			23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998,
    48  			16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702,
    49  			12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208,
    50  			9928, 9747, 9564, 9369, 9193, 9017, 8822, 8639, 8458,
    51  			8270, 8084, 7896, 7710, 7527, 7347, 7156, 6977, 6788,
    52  			6607, 6422, 6236, 6054, 5867, 5684, 5495, 5305, 5128,
    53  			4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, 3509,
    54  			3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846,
    55  			1666, 1483, 1297, 1109, 927, 735, 554, 375, 201,
    56  			128, 0,
    57  		}
    58  
    59  		qvalue = d.quant[0][2] + d.quant[0][53] + d.quant[1][0] + d.quant[1][blockSize-1]
    60  		for i = 0; i < 100; i++ {
    61  			if (qvalue < hash[i]) && (sum < sums[i]) {
    62  				continue
    63  			}
    64  			if ((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50) {
    65  				quality = int32(i + 1)
    66  			}
    67  			break
    68  		}
    69  	} else if !isZero(d.quant[0]) {
    70  		hash := [101]int32{
    71  			510, 505, 422, 380, 355, 338, 326, 318, 311, 305,
    72  			300, 297, 293, 291, 288, 286, 284, 283, 281, 280,
    73  			279, 278, 277, 273, 262, 251, 243, 233, 225, 218,
    74  			211, 205, 198, 193, 186, 181, 177, 172, 168, 164,
    75  			158, 156, 152, 148, 145, 142, 139, 136, 133, 131,
    76  			129, 126, 123, 120, 118, 115, 113, 110, 107, 105,
    77  			102, 100, 97, 94, 92, 89, 87, 83, 81, 79,
    78  			76, 74, 70, 68, 66, 63, 61, 57, 55, 52,
    79  			50, 48, 44, 42, 39, 37, 34, 31, 29, 26,
    80  			24, 21, 18, 16, 13, 11, 8, 6, 3, 2,
    81  			0,
    82  		}
    83  		sums := [101]int32{
    84  			16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859,
    85  			12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027, 9679,
    86  			9368, 9056, 8680, 8331, 7995, 7668, 7376, 7084, 6823,
    87  			6562, 6345, 6125, 5939, 5756, 5571, 5421, 5240, 5086,
    88  			4976, 4829, 4719, 4616, 4463, 4393, 4280, 4166, 4092,
    89  			3980, 3909, 3835, 3755, 3688, 3621, 3541, 3467, 3396,
    90  			3323, 3247, 3170, 3096, 3021, 2952, 2874, 2804, 2727,
    91  			2657, 2583, 2509, 2437, 2362, 2290, 2211, 2136, 2068,
    92  			1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, 1398,
    93  			1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736,
    94  			667, 592, 518, 441, 369, 292, 221, 151, 86,
    95  			64, 0,
    96  		}
    97  
    98  		qvalue = d.quant[0][2] + d.quant[0][53]
    99  		for i = 0; i < 100; i++ {
   100  			if (qvalue < hash[i]) && (sum < sums[i]) {
   101  				continue
   102  			}
   103  			if ((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50) {
   104  				quality = int32(i + 1)
   105  			}
   106  			break
   107  		}
   108  	}
   109  
   110  	return quality
   111  }
   112  
   113  // DecodeWithQuality reads a JPEG image from r and returns it as an image.Image and Quality.
   114  func DecodeWithQuality(r io.Reader) (image.Image, int, error) {
   115  	var d decoder
   116  	img, err := d.decode(r, false)
   117  	if err != nil {
   118  		return img, 0, err
   119  	}
   120  
   121  	quality := d.quality()
   122  	return img, int(quality), err
   123  }
   124  
   125  func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
   126  	return decode(d, r, configOnly)
   127  }
   128  
   129  //go:linkname decode image/jpeg.(*decoder).decode
   130  func decode(d *decoder, r io.Reader, configOnly bool) (image.Image, error)