PDL-IO-Image

 view release on metacpan or  search on metacpan

Image.pd  view on Meta::CPAN


void
save(PDL::IO::Image self, SV * destination, SV * f=NULL, int flags=0);
    PPCODE:
    {
        if (self->dib) {
          FIMEMORY *hmem = NULL;
          BYTE *mem_buffer = NULL;
          DWORD size_in_bytes = 0;
          FREE_IMAGE_FORMAT fif = _sv2fif(f);
          FREE_IMAGE_TYPE fit = FreeImage_GetImageType(self->dib);

          if(SvROK(destination) && SvTYPE(SvRV(destination)) < SVt_PVAV) {
            /* destination is a reference to scalar */
            SV *output = SvRV(destination);
            BYTE *output_ptr = NULL;
            if (fif == FIF_UNKNOWN) croak("FAIL: unspecified format");
            hmem = FreeImage_OpenMemory(NULL, 0);
            if (!FreeImage_SaveToMemory(fif, self->dib, hmem, flags)) {
              warn("FreeImage_SaveToMemory failed (format '%d', image type '%d')", fif, fit);
            }
            FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes);
            sv_setpvn(output, "", 0);
            output_ptr = SvGROW(output, size_in_bytes);
            SvCUR_set(output, size_in_bytes);
            SvPOK_only(output);
            Copy(mem_buffer, output_ptr, size_in_bytes, BYTE);
            FreeImage_CloseMemory(hmem);
          }
          else {
            /* destination is a filename */
            STRLEN flen = 0;
            char * filename = SvPV(destination, flen);
            if (!filename || flen<=0) croak("FAIL: invalid filename");
            if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(filename);
            if (fif == FIF_UNKNOWN) croak("FAIL: unspecified format");
            if (!FreeImage_Save(fif, self->dib, filename, flags)) {
              warn("FreeImage_Save failed (format '%d', image type '%d')", fif, fit);
            }
          }
        }
        XPUSHs(ST(0)); /* return self */
    }

pdl*
palette_to_pdl(PDL::IO::Image self)
    CODE:
    {
        pdl *pal_pdl = NULL;
        PDL_Indx dims[] = {0, 0, 0};
        int cu = FreeImage_GetColorsUsed(self->dib);
        if (cu==0) XSRETURN_UNDEF;

        PDL_Byte *pdata;
        int i;
        dims[0] = 3;
        dims[1] = cu;
        pal_pdl = PDL->pdlnew();
        pal_pdl->datatype = PDL_B;
        PDL->setdims (pal_pdl, dims, 2);
        PDL->allocdata (pal_pdl);
        pdata = (PDL_Byte *) pal_pdl->data;
        RGBQUAD *pal = FreeImage_GetPalette(self->dib);
        for (i = 0; i < cu; i++) {
          pdata[i*3]     = (PDL_Byte) pal[i].rgbRed;
          pdata[i*3 + 1] = (PDL_Byte) pal[i].rgbGreen;
          pdata[i*3 + 2] = (PDL_Byte) pal[i].rgbBlue;
        }
        RETVAL = pal_pdl;
    }
    OUTPUT:
        RETVAL

pdl*
pixels_to_pdl(PDL::IO::Image self, long x1=0, long x2=0, long y1=0, long y2=0)
    CODE:
    {
        pdl *bmp_pdl = NULL;
        PDL_Indx dims[] = {0, 0, 0};
        PDL_Indx x, y, wxh;
        unsigned long w, h, wp, hp;
        int bpp, it;

        w   = FreeImage_GetWidth(self->dib);
        h   = FreeImage_GetHeight(self->dib);
        bpp = FreeImage_GetBPP(self->dib);
        it  = FreeImage_GetImageType(self->dib);
        wp  = w;
        hp  = h;

        if (!FreeImage_HasPixels(self->dib) || w == 0 || h == 0) {
          warn("FAIL: no pixels");
          XSRETURN_UNDEF;
        }

        /* handle negative boundaries */
        if (x1 < 0)  x1 = w - 1 + x1;
        if (y1 < 0)  y1 = h - 1 + y1;
        if (x2 <= 0) x2 = w - 1 + x2;
        if (y2 <= 0) y2 = h - 1 + y2;
        /* handle region selection */
        wp = (x2 - x1 + 1);
        hp = (y2 - y1 + 1);
        wxh = wp * hp;

        if (x1>x2 || y1>y2 || x1<0 || y1<0 || x2<0 || y2<0 || wp>w || hp>h) {
          warn("FAIL: invalid region");
          XSRETURN_UNDEF;
        }

        switch (it) {
          case FIT_BITMAP:      /* Standard image: 1-, 4-, 8-, 16-, 24-, 32-bit */
            if (bpp==32) {
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 4;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                RGBQUAD *bits = (RGBQUAD*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Byte) bits[x+x1].rgbRed;
                  pdata[y*wp + x + wxh]   = (PDL_Byte) bits[x+x1].rgbGreen;
                  pdata[y*wp + x + 2*wxh] = (PDL_Byte) bits[x+x1].rgbBlue;
                  pdata[y*wp + x + 3*wxh] = (PDL_Byte) bits[x+x1].rgbReserved;
                }
              }
            }
            else if (bpp==24) {
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 3;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                RGBTRIPLE *bits = (RGBTRIPLE*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Byte) bits[x+x1].rgbtRed;
                  pdata[y*wp + x + wxh]   = (PDL_Byte) bits[x+x1].rgbtGreen;
                  pdata[y*wp + x + 2*wxh] = (PDL_Byte) bits[x+x1].rgbtBlue;
                }
              }
            }
            else if (bpp==16) {
              unsigned red_mask, green_mask, blue_mask;
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 3;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              red_mask   = FreeImage_GetRedMask(self->dib);
              green_mask = FreeImage_GetGreenMask(self->dib);
              blue_mask  = FreeImage_GetBlueMask(self->dib);
              if ( (red_mask == FI16_565_RED_MASK) && (green_mask == FI16_565_GREEN_MASK) && (blue_mask == FI16_565_BLUE_MASK) ) {
                for(y = 0; y < hp; y++) {
                  WORD *bits = (WORD*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                  for(x = 0; x < wp; x++) {
                    PDL_Byte r5 = (PDL_Byte)((bits[x+x1] & FI16_565_RED_MASK)   >> FI16_565_RED_SHIFT)  ;
                    PDL_Byte g6 = (PDL_Byte)((bits[x+x1] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT);
                    PDL_Byte b5 = (PDL_Byte)((bits[x+x1] & FI16_565_BLUE_MASK)  >> FI16_565_BLUE_SHIFT) ;
                    /* http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888 */
                    pdata[y*wp + x]         = (r5 << 3) | (r5 >> 2);
                    pdata[y*wp + x + wxh]   = (g6 << 2) | (g6 >> 4);
                    pdata[y*wp + x + 2*wxh] = (b5 << 3) | (b5 >> 2);
                  }
                }
              }
              else {
                for(y = 0; y < hp; y++) {
                  WORD *bits = (WORD*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                  for(x = 0; x < wp; x++) {
                    PDL_Byte r5 = (PDL_Byte)((bits[x+x1] & FI16_555_RED_MASK)   >> FI16_555_RED_SHIFT)  ;
                    PDL_Byte g5 = (PDL_Byte)((bits[x+x1] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT);
                    PDL_Byte b5 = (PDL_Byte)((bits[x+x1] & FI16_555_BLUE_MASK)  >> FI16_555_BLUE_SHIFT) ;
                    pdata[y*wp + x]         = (r5 << 3) | (r5 >> 2);
                    pdata[y*wp + x + wxh]   = (g5 << 3) | (g5 >> 2);
                    pdata[y*wp + x + 2*wxh] = (b5 << 3) | (b5 >> 2);
                  }
                }
              }
            }
            else if (bpp==8) {
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                BYTE *bits = FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = (PDL_Byte) bits[x+x1];
                }
              }
            }
            else if (bpp==4) {
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                BYTE *bits = FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = (PDL_Byte) ((bits[(x+x1)/2] >> 4*(1-(x+x1)%2)) & 0x0F);
                }
              }
            }
            else if (bpp==1) {
              PDL_Byte *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_B;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Byte *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                BYTE *bits = FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = (PDL_Byte) ((bits[(x+x1)/8] >> (7-(x+x1)%8)) & 0x01);
                }
              }
            }
            else {
              warn("FAIL: unknown bits per pixel '%d'", bpp);
            }
            break;
          case FIT_UINT16:      /* Array of unsigned short: unsigned 16-bit */
            {
              PDL_Ushort *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_US;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Ushort *) bmp_pdl->data;

              for(y = 0; y < hp; y++) {
                PDL_Ushort *bits = (PDL_Ushort*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = bits[x+x1];
                }
              }
            }
            break;
          case FIT_INT16:       /* Array of short: signed 16-bit */
            {
              PDL_Short *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_S;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Short *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                PDL_Short *bits = (PDL_Short*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = bits[x+x1];
                }
              }
            }
            break;
          case FIT_UINT32:      /* Array of unsigned long: unsigned 32-bit */
            { /* XXX hack: using INT64 for UINT32 */
              PDL_LongLong *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_LL;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_LongLong *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                DWORD *bits = (DWORD*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = (PDL_LongLong)bits[x+x1];
                }
              }
            }
            break;
          case FIT_INT32:       /* Array of long: signed 32-bit */
            {
              PDL_Long *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_L;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Long *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                PDL_Long *bits = (PDL_Long*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = bits[x+x1];
                }
              }
            }
            break;
          case FIT_FLOAT:       /* Array of float: 32-bit IEEE floating point */
            {
              PDL_Float *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_F;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Float *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                PDL_Float *bits = (PDL_Float*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = bits[x+x1];
                }
              }
            }
            break;
          case FIT_DOUBLE:      /* Array of double: 64-bit IEEE floating point */
            {
              PDL_Double *pdata;
              dims[0] = wp;
              dims[1] = hp;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_D;
              PDL->setdims (bmp_pdl, dims, 2);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Double *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                PDL_Double *bits = (PDL_Double*)FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x] = bits[x+x1];
                }
              }
            }
            break;
          case FIT_COMPLEX:     /* Array of FICOMPLEX: 2 x 64-bit IEEE floating point */
            warn("FAIL: FIT_COMPLEX not supported");
            /* for(y = 0; y < hp; y++) {
             *   FICOMPLEX *bits = (FICOMPLEX *)FreeImage_GetScanLine(self->dib, h-y-1-y1);
             *   for(x = 0; x < wp; x++) {
             *     pdata[y*wp + x] = (PDL_Double) bits[x+x1].r;
             *     pdata[y*wp + x] = (PDL_Double) bits[x+x1].i;
             *   }
             * }
             */
            break;
          case FIT_RGB16:       /* 48-bit RGB image: 3 x 16-bit */
            {
              PDL_Ushort *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 3;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_US;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Ushort *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                FIRGB16 *bits = (FIRGB16*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Ushort) bits[x+x1].red;
                  pdata[y*wp + x + wxh]   = (PDL_Ushort) bits[x+x1].green;
                  pdata[y*wp + x + 2*wxh] = (PDL_Ushort) bits[x+x1].blue;
                }
              }
            }
            break;
          case FIT_RGBA16:      /* 64-bit RGBA image: 4 x 16-bit */
            {
              PDL_Ushort *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 4;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_US;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Ushort *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                FIRGBA16 *bits = (FIRGBA16*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Ushort) bits[x+x1].red;
                  pdata[y*wp + x + wxh]   = (PDL_Ushort) bits[x+x1].green;
                  pdata[y*wp + x + 2*wxh] = (PDL_Ushort) bits[x+x1].blue;
                  pdata[y*wp + x + 3*wxh] = (PDL_Ushort) bits[x+x1].alpha;
                }
              }
            }
            break;
          case FIT_RGBF:        /* 96-bit RGB float image: 3 x 32-bit IEEE floating point */
            {
              PDL_Float *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 3;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_F;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Float *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                FIRGBF *bits = (FIRGBF*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Float) bits[x+x1].red;
                  pdata[y*wp + x + wxh]   = (PDL_Float) bits[x+x1].green;
                  pdata[y*wp + x + 2*wxh] = (PDL_Float) bits[x+x1].blue;
                }
              }
            }
            break;
          case FIT_RGBAF:       /* 128-bit RGBA float image: 4 x 32-bit IEEE floating point */
            {
              PDL_Float *pdata;
              dims[0] = wp;
              dims[1] = hp;
              dims[2] = 4;
              bmp_pdl = PDL->pdlnew();
              bmp_pdl->datatype = PDL_F;
              PDL->setdims (bmp_pdl, dims, 3);
              PDL->allocdata (bmp_pdl);
              pdata = (PDL_Float *) bmp_pdl->data;
              for(y = 0; y < hp; y++) {
                FIRGBAF *bits = (FIRGBAF*) FreeImage_GetScanLine(self->dib, h-y-1-y1);
                for(x = 0; x < wp; x++) {
                  pdata[y*wp + x]         = (PDL_Float) bits[x+x1].red;
                  pdata[y*wp + x + wxh]   = (PDL_Float) bits[x+x1].green;
                  pdata[y*wp + x + 2*wxh] = (PDL_Float) bits[x+x1].blue;
                  pdata[y*wp + x + 3*wxh] = (PDL_Float) bits[x+x1].alpha;
                }
              }
            }
            break;
          default:
            warn("FAIL: unknown image type '%d'", it);
            break;
        }

        if (bmp_pdl == NULL) XSRETURN_UNDEF;
        RETVAL = bmp_pdl;
    }
    OUTPUT:
        RETVAL

void
DESTROY(PDL::IO::Image self)
    CODE:
        if (self->dib != NULL) FreeImage_Unload(self->dib);
        Safefree(self);

ENDXS

############################################################### PM part
pp_bless('PDL');
pp_add_exported('wimage');
pp_add_exported('rimage');
pp_addpm( <<'ENDPM' );
use strict;
use warnings;
use Carp;

#XXX FIXME probably OK for now
{
  no strict 'refs';
  *{'PDL::wimage'} = \&PDL::IO::Image::wimage;
}

sub _val2list {
  return @{$_[0]} if ref $_[0] eq 'ARRAY';
  return $_[0];
};

sub rimage {
  my $options = ref $_[-1] eq 'HASH' ? pop : {};
  my $filename = shift;
  $options->{format} = "AUTO" unless defined $options->{format};
  $options->{format_flag} = 0 unless defined $options->{format_flag};
  $options->{page} = 0        unless defined $options->{page};
  my $pimage = PDL::IO::Image->new_from_file($filename, $options->{format}, $options->{format_flag}, $options->{page});

  if (my $flip = $options->{flip}) {



( run in 1.803 second using v1.01-cache-2.11-cpan-39bf76dae61 )