github.com/unidoc/unidoc@v2.2.0+incompatible/pdf/model/sampling/resample.go (about)

     1  /*
     2   * This file is subject to the terms and conditions defined in
     3   * file 'LICENSE.md', which is part of this source code package.
     4   */
     5  
     6  package sampling
     7  
     8  // Resample the raw data which is in 8-bit (byte) format as a different
     9  // bit count per sample, up to 32 bits (uint32).
    10  func ResampleBytes(data []byte, bitsPerSample int) []uint32 {
    11  	samples := []uint32{}
    12  
    13  	bitsLeftPerSample := bitsPerSample
    14  	var sample uint32
    15  	var remainder byte
    16  	remainderBits := 0
    17  
    18  	index := 0
    19  
    20  	i := 0
    21  	for i < len(data) {
    22  		// Start with the remainder.
    23  		if remainderBits > 0 {
    24  			take := remainderBits
    25  			if bitsLeftPerSample < take {
    26  				take = bitsLeftPerSample
    27  			}
    28  
    29  			sample = (sample << uint(take)) | uint32(remainder>>uint(8-take))
    30  			remainderBits -= take
    31  			if remainderBits > 0 {
    32  				remainder = remainder << uint(take)
    33  			} else {
    34  				remainder = 0
    35  			}
    36  			bitsLeftPerSample -= take
    37  			if bitsLeftPerSample == 0 {
    38  				//samples[index] = sample
    39  				samples = append(samples, sample)
    40  				bitsLeftPerSample = bitsPerSample
    41  				sample = 0
    42  				index++
    43  			}
    44  		} else {
    45  			// Take next byte
    46  			b := data[i]
    47  			i++
    48  
    49  			// 8 bits.
    50  			take := 8
    51  			if bitsLeftPerSample < take {
    52  				take = bitsLeftPerSample
    53  			}
    54  			remainderBits = 8 - take
    55  			sample = (sample << uint(take)) | uint32(b>>uint(remainderBits))
    56  
    57  			if take < 8 {
    58  				remainder = b << uint(take)
    59  			}
    60  
    61  			bitsLeftPerSample -= take
    62  			if bitsLeftPerSample == 0 {
    63  				//samples[index] = sample
    64  				samples = append(samples, sample)
    65  				bitsLeftPerSample = bitsPerSample
    66  				sample = 0
    67  				index++
    68  			}
    69  		}
    70  	}
    71  
    72  	// Take care of remaining samples (if enough data available).
    73  	for remainderBits >= bitsPerSample {
    74  		take := remainderBits
    75  		if bitsLeftPerSample < take {
    76  			take = bitsLeftPerSample
    77  		}
    78  
    79  		sample = (sample << uint(take)) | uint32(remainder>>uint(8-take))
    80  		remainderBits -= take
    81  		if remainderBits > 0 {
    82  			remainder = remainder << uint(take)
    83  		} else {
    84  			remainder = 0
    85  		}
    86  		bitsLeftPerSample -= take
    87  		if bitsLeftPerSample == 0 {
    88  			//samples[index] = sample
    89  			samples = append(samples, sample)
    90  			bitsLeftPerSample = bitsPerSample
    91  			sample = 0
    92  			index++
    93  		}
    94  	}
    95  
    96  	return samples
    97  }
    98  
    99  // Resample the raw data which is in <=32-bit (uint32) format as a different
   100  // bit count per sample, up to 32 bits (uint32).
   101  //
   102  // bitsPerOutputSample is the number of bits for each output sample (up to 32)
   103  // bitsPerInputSample is the number of bits used in each input sample (up to 32)
   104  func ResampleUint32(data []uint32, bitsPerInputSample int, bitsPerOutputSample int) []uint32 {
   105  	samples := []uint32{}
   106  
   107  	bitsLeftPerSample := bitsPerOutputSample
   108  	var sample uint32
   109  	var remainder uint32
   110  	remainderBits := 0
   111  
   112  	index := 0
   113  
   114  	i := 0
   115  	for i < len(data) {
   116  		// Start with the remainder.
   117  		if remainderBits > 0 {
   118  			take := remainderBits
   119  			if bitsLeftPerSample < take {
   120  				take = bitsLeftPerSample
   121  			}
   122  
   123  			sample = (sample << uint(take)) | uint32(remainder>>uint(bitsPerInputSample-take))
   124  			remainderBits -= take
   125  			if remainderBits > 0 {
   126  				remainder = remainder << uint(take)
   127  			} else {
   128  				remainder = 0
   129  			}
   130  			bitsLeftPerSample -= take
   131  			if bitsLeftPerSample == 0 {
   132  				//samples[index] = sample
   133  				samples = append(samples, sample)
   134  				bitsLeftPerSample = bitsPerOutputSample
   135  				sample = 0
   136  				index++
   137  			}
   138  		} else {
   139  			// Take next byte
   140  			b := data[i]
   141  			i++
   142  
   143  			// 32 bits.
   144  			take := bitsPerInputSample
   145  			if bitsLeftPerSample < take {
   146  				take = bitsLeftPerSample
   147  			}
   148  			remainderBits = bitsPerInputSample - take
   149  			sample = (sample << uint(take)) | uint32(b>>uint(remainderBits))
   150  
   151  			if take < bitsPerInputSample {
   152  				remainder = b << uint(take)
   153  			}
   154  
   155  			bitsLeftPerSample -= take
   156  			if bitsLeftPerSample == 0 {
   157  				//samples[index] = sample
   158  				samples = append(samples, sample)
   159  				bitsLeftPerSample = bitsPerOutputSample
   160  				sample = 0
   161  				index++
   162  			}
   163  		}
   164  	}
   165  
   166  	// Take care of remaining samples (if enough data available).
   167  	for remainderBits >= bitsPerOutputSample {
   168  		take := remainderBits
   169  		if bitsLeftPerSample < take {
   170  			take = bitsLeftPerSample
   171  		}
   172  
   173  		sample = (sample << uint(take)) | uint32(remainder>>uint(bitsPerInputSample-take))
   174  		remainderBits -= take
   175  		if remainderBits > 0 {
   176  			remainder = remainder << uint(take)
   177  		} else {
   178  			remainder = 0
   179  		}
   180  		bitsLeftPerSample -= take
   181  		if bitsLeftPerSample == 0 {
   182  			samples = append(samples, sample)
   183  			bitsLeftPerSample = bitsPerOutputSample
   184  			sample = 0
   185  			index++
   186  		}
   187  	}
   188  
   189  	// If there are partial output samples, pad with 0s.
   190  	if bitsLeftPerSample > 0 && bitsLeftPerSample < bitsPerOutputSample {
   191  		sample <<= uint(bitsLeftPerSample)
   192  		samples = append(samples, sample)
   193  	}
   194  
   195  	return samples
   196  }