@@ -433,72 +433,32 @@ fn cmyk_to_rgb(cmyk: &[u8]) -> [u8; 3] {
433
433
]
434
434
}
435
435
436
- enum DtypeContainer < ' a , T > {
437
- Slice ( & ' a [ T ] ) ,
438
- Vec ( Vec < T > ) ,
439
- }
440
-
441
- impl < T > DtypeContainer < ' _ , T > {
442
- fn as_slice ( & self ) -> & [ T ] {
443
- match self {
444
- DtypeContainer :: Slice ( slice) => slice,
445
- DtypeContainer :: Vec ( vec) => vec,
446
- }
447
- }
448
- }
449
-
450
- fn u8_slice_as_f32 ( buf : & [ u8 ] ) -> ImageResult < DtypeContainer < f32 > > {
451
- match bytemuck:: try_cast_slice ( buf) {
452
- Ok ( slice) => Ok ( DtypeContainer :: < f32 > :: Slice ( slice) ) ,
453
- Err ( err) => {
454
- match err {
455
- bytemuck:: PodCastError :: TargetAlignmentGreaterAndInputNotAligned => {
456
- // If the buffer is not aligned for a f32 slice, copy the buffer into a new Vec<f32>
457
- let mut vec = vec ! [ 0.0 ; buf. len( ) / 4 ] ;
458
- for ( i, chunk) in buf. chunks_exact ( 4 ) . enumerate ( ) {
459
- let f32_val = f32:: from_ne_bytes ( [ chunk[ 0 ] , chunk[ 1 ] , chunk[ 2 ] , chunk[ 3 ] ] ) ;
460
- vec[ i] = f32_val;
461
- }
462
- Ok ( DtypeContainer :: Vec ( vec) )
463
- }
464
- _ => {
465
- // If the buffer is not the correct length for a f32 slice, err.
466
- Err ( ImageError :: Parameter ( ParameterError :: from_kind (
467
- ParameterErrorKind :: Generic ( format ! ( "{:?}" , err) ) ,
468
- ) ) )
469
- }
470
- }
471
- }
472
- }
473
- }
474
-
475
- fn u8_slice_as_u16 ( buf : & [ u8 ] ) -> ImageResult < DtypeContainer < u16 > > {
476
- match bytemuck:: try_cast_slice ( buf) {
477
- Ok ( slice) => Ok ( DtypeContainer :: < u16 > :: Slice ( slice) ) ,
478
- Err ( err) => {
436
+ /// Convert a slice of sample bytes to its semantic type, being a `Pod`.
437
+ fn u8_slice_as_pod < P : bytemuck:: Pod > ( buf : & [ u8 ] ) -> ImageResult < std:: borrow:: Cow < ' _ , [ P ] > > {
438
+ bytemuck:: try_cast_slice ( buf)
439
+ . map ( std:: borrow:: Cow :: Borrowed )
440
+ . or_else ( |err| {
479
441
match err {
480
442
bytemuck:: PodCastError :: TargetAlignmentGreaterAndInputNotAligned => {
481
- // If the buffer is not aligned for a f32 slice, copy the buffer into a new Vec<f32>
482
- let mut vec = vec ! [ 0 ; buf. len( ) / 2 ] ;
483
- for ( i, chunk) in buf. chunks_exact ( 2 ) . enumerate ( ) {
484
- let u16_val = u16:: from_ne_bytes ( [ chunk[ 0 ] , chunk[ 1 ] ] ) ;
485
- vec[ i] = u16_val;
486
- }
487
- Ok ( DtypeContainer :: Vec ( vec) )
443
+ // If the buffer is not aligned for a native slice, copy the buffer into a Vec,
444
+ // aligning it in the process. This is only done if the element count can be
445
+ // represented exactly.
446
+ let vec = bytemuck:: allocation:: pod_collect_to_vec ( buf) ;
447
+ Ok ( std:: borrow:: Cow :: Owned ( vec) )
488
448
}
449
+ /* only expecting: bytemuck::PodCastError::OutputSliceWouldHaveSlop */
489
450
_ => {
490
- // If the buffer is not aligned or the correct length for a u16 slice, err.
491
- //
492
- // `bytemuck::PodCastError` of bytemuck-1.2.0 does not implement
493
- // `Error` and `Display` trait.
451
+ // `bytemuck::PodCastError` of bytemuck-1.2.0 does not implement `Error` and
452
+ // `Display` trait.
494
453
// See <https://github.com/Lokathor/bytemuck/issues/22>.
495
454
Err ( ImageError :: Parameter ( ParameterError :: from_kind (
496
- ParameterErrorKind :: Generic ( format ! ( "{err:?}" ) ) ,
455
+ ParameterErrorKind :: Generic ( format ! (
456
+ "Casting samples to their representation failed: {err:?}" ,
457
+ ) ) ,
497
458
) ) )
498
459
}
499
460
}
500
- }
501
- }
461
+ } )
502
462
}
503
463
504
464
impl < W : Write + Seek > TiffEncoder < W > {
@@ -562,20 +522,24 @@ impl<W: Write + Seek> TiffEncoder<W> {
562
522
ExtendedColorType :: Rgb8 => encoder. write_image :: < RGB8 > ( width, height, buf) ,
563
523
ExtendedColorType :: Rgba8 => encoder. write_image :: < RGBA8 > ( width, height, buf) ,
564
524
ExtendedColorType :: L16 => {
565
- encoder. write_image :: < Gray16 > ( width, height, u8_slice_as_u16 ( buf) ?. as_slice ( ) )
525
+ encoder. write_image :: < Gray16 > ( width, height, u8_slice_as_pod :: < u16 > ( buf) ?. as_ref ( ) )
566
526
}
567
527
ExtendedColorType :: Rgb16 => {
568
- encoder. write_image :: < RGB16 > ( width, height, u8_slice_as_u16 ( buf) ?. as_slice ( ) )
528
+ encoder. write_image :: < RGB16 > ( width, height, u8_slice_as_pod :: < u16 > ( buf) ?. as_ref ( ) )
569
529
}
570
530
ExtendedColorType :: Rgba16 => {
571
- encoder. write_image :: < RGBA16 > ( width, height, u8_slice_as_u16 ( buf) ?. as_slice ( ) )
572
- }
573
- ExtendedColorType :: Rgb32F => {
574
- encoder. write_image :: < RGB32Float > ( width, height, u8_slice_as_f32 ( buf) ?. as_slice ( ) )
575
- }
576
- ExtendedColorType :: Rgba32F => {
577
- encoder. write_image :: < RGBA32Float > ( width, height, u8_slice_as_f32 ( buf) ?. as_slice ( ) )
531
+ encoder. write_image :: < RGBA16 > ( width, height, u8_slice_as_pod :: < u16 > ( buf) ?. as_ref ( ) )
578
532
}
533
+ ExtendedColorType :: Rgb32F => encoder. write_image :: < RGB32Float > (
534
+ width,
535
+ height,
536
+ u8_slice_as_pod :: < f32 > ( buf) ?. as_ref ( ) ,
537
+ ) ,
538
+ ExtendedColorType :: Rgba32F => encoder. write_image :: < RGBA32Float > (
539
+ width,
540
+ height,
541
+ u8_slice_as_pod :: < f32 > ( buf) ?. as_ref ( ) ,
542
+ ) ,
579
543
_ => {
580
544
return Err ( ImageError :: Unsupported (
581
545
UnsupportedError :: from_format_and_kind (
0 commit comments