PDL-IO-Image

 view release on metacpan or  search on metacpan

Image.pd  view on Meta::CPAN

            }
            break;
          case FIT_RGBAF:       /* 128-bit RGBA float image: 4 x 32-bit IEEE floating point */
            {
              PDL_Float *pdata = (PDL_Float *) pixels->data;
              for(y = 0; y < h; y++) {
                FIRGBAF *bits = (FIRGBAF*) FreeImage_GetScanLine(dib, y);
                for(x = 0; x < w; x++) {
                  bits[x].red   = pdata[(h-1-y)*w + x];
                  bits[x].green = pdata[(h-1-y)*w + x + wxh];
                  bits[x].blue  = pdata[(h-1-y)*w + x + 2*wxh];
                  bits[x].alpha = pdata[(h-1-y)*w + x + 3*wxh];
                }
              }
            }
            break;
          default:
            warn("FAIL: unknown image type '%d'", fit);
            break;
        }

        cu = FreeImage_GetColorsUsed(dib);
        if (palsize > 0 && cu > 0) {
          if (palsize > cu) palsize = cu;
          BYTE *pdata = palette->data;
          RGBQUAD *pal = FreeImage_GetPalette(dib);
          for (i = 0; i < palsize; i++) {
            pal[i].rgbRed      = pdata[i*3];
            pal[i].rgbGreen    = pdata[i*3 + 1];
            pal[i].rgbBlue     = pdata[i*3 + 2];
            pal[i].rgbReserved = 0;
          }
        }
        if (palsize > 0 && cu == 0) {
          warn("ignoring palete piddle");
        }

        Newz(0, RETVAL, 1, struct img_struct);
        if (RETVAL == NULL) croak("FAIL: Newz failed");

        RETVAL->dib = dib;
    }
    OUTPUT:
        RETVAL

PDL::IO::Image
clone(PDL::IO::Image self)
    CODE:
    {
      Newz(0, RETVAL, 1, struct img_struct);
      if (RETVAL == NULL) croak("FAIL: Newz failed");
      FIBITMAP *newdib = FreeImage_Clone(self->dib);
      if (newdib == NULL) croak("FAIL: FreeImage_Clone failed");
      RETVAL->dib = newdib;
    }
    OUTPUT:
        RETVAL

void
dump_bitmap(PDL::IO::Image self, int target_bpp=0)
    PPCODE:
    {
      SV *bmp_sv, *pal_sv;
      unsigned char *bmp = NULL, *pal = NULL;
      unsigned w, h, bpp, cu, it, sz, szp, szl, y, i;
      FIBITMAP *newdib = NULL, *b = NULL;

      /* FIRST: we need FIT_BITMAP */
      it  = FreeImage_GetImageType(self->dib);
      if (it==FIT_RGB16 || it==FIT_RGBA16 || it==FIT_RGBF || it==FIT_RGBAF) {
        newdib = FreeImage_ToneMapping(self->dib, FITMO_REINHARD05, 0, 0);
      }
      else {
        newdib = FreeImage_ConvertToType(self->dib, FIT_BITMAP, 1);
      }
      if (!newdib) {
        warn("dump_bitmap failed to convert image into a BITMAP");
        XSRETURN_UNDEF;
      }

      /* SECOND: we only want 8/24/32-bpp output */
      bpp = FreeImage_GetBPP(newdib);
      if (target_bpp!=8 && target_bpp!=24 && target_bpp!=32) target_bpp = 0;
      if (target_bpp==0 && (bpp==1 || bpp==4 || bpp==8))     target_bpp = 8;
      if (target_bpp==0 && (bpp==16 || bpp==24))             target_bpp = 24;
      if (target_bpp==0 && bpp>=32)                          target_bpp = 32;

      if (target_bpp==8 && bpp!=8) {
        /* XXX BEWARE: high-color bitmap (16, 24 or 32-bit) is converted into a greyscale bitmap */
        b = FreeImage_ConvertTo8Bits(newdib);
      }
      else if (target_bpp==24 && bpp!=24) {
        b = FreeImage_ConvertTo24Bits(newdib);
      }
      else if (target_bpp==32 && bpp!=32) {
        b = FreeImage_ConvertTo32Bits(newdib);
      }
      if (b) {
        FreeImage_Unload(newdib);
        newdib = b;
      }

      bpp = FreeImage_GetBPP(newdib);
      w   = FreeImage_GetWidth(newdib);
      h   = FreeImage_GetHeight(newdib);
      cu  = FreeImage_GetColorsUsed(newdib);
      szp = (bpp/8);    /* pixel size */
      szl = szp * w;    /* line size */
      sz  = szl * h;    /* picture size */

      if (bpp==32 || bpp==24 || bpp==8) {
        bmp_sv = NEWSV(0, sz);
        SvPOK_only(bmp_sv);
        SvCUR_set(bmp_sv, sz);
        bmp = (unsigned char *)SvPV_nolen(bmp_sv);
        for(i = 0, y = 0; y < h; y++) {
          BYTE *bits = FreeImage_GetScanLine(newdib, h-y-1);
          Copy(bits, bmp + i, szl, BYTE);
          i += szl;
        }
        XPUSHs(sv_2mortal(newSViv(w)));
        XPUSHs(sv_2mortal(newSViv(h)));
        XPUSHs(sv_2mortal(newSViv(bpp)));
        XPUSHs(sv_2mortal(bmp_sv));
        if (cu>0) {
          RGBQUAD *p = FreeImage_GetPalette(newdib);
          pal_sv = NEWSV(0, cu*3);
          SvPOK_only(pal_sv);
          SvCUR_set(pal_sv, cu*3);
          pal = (unsigned char *)SvPV_nolen(pal_sv);
          for (i = 0; i < cu; i++) {
            pal[i*3]     = (unsigned char) p[i].rgbRed;
            pal[i*3 + 1] = (unsigned char) p[i].rgbGreen;
            pal[i*3 + 2] = (unsigned char) p[i].rgbBlue;
          }
          XPUSHs(sv_2mortal(pal_sv));
        }
      }
      else {
        warn("dump_bitmap: unexpected bpp");
      }

      FreeImage_Unload(newdib);
    }

const char*
free_image_version(SV *class)
    CODE:
        RETVAL = FreeImage_GetVersion();
    OUTPUT:
        RETVAL

void
format_list(SV *class)
    PPCODE:
    {
        int i;
        for(i = 0; i < FreeImage_GetFIFCount(); i++) {
          if(FreeImage_IsPluginEnabled((FREE_IMAGE_FORMAT)i)) {
            const char *f = FreeImage_GetFormatFromFIF((FREE_IMAGE_FORMAT)i);
            XPUSHs(sv_2mortal(newSVpvn(f, strlen(f))));
          }
        }
    }

const char*
format_extension_list(SV *class, SV *f)
    CODE:
        RETVAL = FreeImage_GetFIFExtensionList(_sv2fif(f));
    OUTPUT:
        RETVAL

const char*
format_mime_type(SV *class, SV *f)
    CODE:
        RETVAL = FreeImage_GetFIFMimeType(_sv2fif(f));
    OUTPUT:
        RETVAL

const char*
format_description(SV *class, SV *f)
    CODE:
        RETVAL = FreeImage_GetFIFDescription(_sv2fif(f));
    OUTPUT:
        RETVAL

int
format_can_read(SV *class, SV *f)
    CODE:
        RETVAL = FreeImage_IsPluginEnabled(_sv2fif(f)) && FreeImage_FIFSupportsReading(_sv2fif(f));
    OUTPUT:
        RETVAL

int
format_can_write(SV *class, SV *f)
    CODE:
        RETVAL = FreeImage_IsPluginEnabled(_sv2fif(f)) && FreeImage_FIFSupportsWriting(_sv2fif(f));
    OUTPUT:
        RETVAL

int
format_can_export_type(SV *class, SV *f, SV *t)
    CODE:
        RETVAL = FreeImage_FIFSupportsExportType(_sv2fif(f), _sv2fit(t));
    OUTPUT:
        RETVAL

int
format_can_export_bpp(SV *class, SV *f, int bpp)
    CODE:
        RETVAL = FreeImage_FIFSupportsExportBPP(_sv2fif(f), bpp);
    OUTPUT:
        RETVAL

const char *
format_from_mime(SV *class, const char *mime)
    CODE:
        RETVAL = FreeImage_GetFormatFromFIF(FreeImage_GetFIFFromMime(mime));
    OUTPUT:
        RETVAL

const char *
format_from_file(SV *class, const char *filename)
    CODE:
        int fif = FreeImage_GetFileType(filename, 0);
        if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(filename);
        RETVAL = FreeImage_GetFormatFromFIF(fif);
    OUTPUT:
        RETVAL

const char*
get_image_type(PDL::IO::Image self)
    CODE:
        RETVAL = _fit2str(FreeImage_GetImageType(self->dib));
    OUTPUT:
        RETVAL

unsigned
get_colors_used(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetColorsUsed(self->dib);
    OUTPUT:
        RETVAL

unsigned
get_bpp(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetBPP(self->dib);
    OUTPUT:
        RETVAL

unsigned
get_width(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetWidth(self->dib);
    OUTPUT:
        RETVAL

unsigned
get_height(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetHeight(self->dib);
    OUTPUT:
        RETVAL

unsigned
get_dots_per_meter_x(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetDotsPerMeterX(self->dib);
    OUTPUT:
        RETVAL

void
set_dots_per_meter_x(PDL::IO::Image self, unsigned res)
    PPCODE:
        FreeImage_SetDotsPerMeterX(self->dib, res);
        XPUSHs(ST(0)); /* return self */

unsigned
get_dots_per_meter_y(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetDotsPerMeterY(self->dib);
    OUTPUT:
        RETVAL

void
set_dots_per_meter_y(PDL::IO::Image self, unsigned res)
    PPCODE:
        FreeImage_SetDotsPerMeterY(self->dib, res);
        XPUSHs(ST(0)); /* return self */

const char*
get_color_type(PDL::IO::Image self)
    CODE:
        RETVAL = _fic2str(FreeImage_GetColorType(self->dib));
    OUTPUT:
        RETVAL

int
is_transparent(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_IsTransparent(self->dib);
    OUTPUT:
        RETVAL

int
get_transparent_index(PDL::IO::Image self)
    CODE:
        RETVAL = FreeImage_GetTransparentIndex(self->dib);
    OUTPUT:
        RETVAL

void
set_transparent_index(PDL::IO::Image self, int index)
    PPCODE:
        FreeImage_SetTransparentIndex(self->dib, index);
        XPUSHs(ST(0)); /* return self */

void
flip_horizontal(PDL::IO::Image self)
    PPCODE:
        if(!FreeImage_FlipHorizontal(self->dib)) {
          warn("FreeImage_FlipHorizontal failed");
        }
        XPUSHs(ST(0)); /* return self */

void
flip_vertical(PDL::IO::Image self)
    PPCODE:
        if(!FreeImage_FlipVertical(self->dib)) {
          warn("FreeImage_FlipVertical failed");
        }
        XPUSHs(ST(0)); /* return self */

void
convert_image_type(PDL::IO::Image self, SV * dst_image_type, int scale_linear=1)
    PPCODE:
    {
        FREE_IMAGE_TYPE fit = _sv2fit(dst_image_type);
        if (fit == FIT_UNKNOWN) {
          warn("invalid dst_image_type");
        }
        else {
          FIBITMAP *newdib = FreeImage_ConvertToType(self->dib, fit, scale_linear);
          if (newdib) {
            if (self->dib) FreeImage_Unload(self->dib);
            self->dib = newdib;
          }
          else {
            warn("FreeImage_ConvertToType (fit=%d) failed", fit);
          }
        }
        XPUSHs(ST(0)); /* return self */
    }

void
adjust_colors(PDL::IO::Image self, double brightness=0, double contrast=0, double gamma=0, int invert=0)
    PPCODE:
        if(!FreeImage_AdjustColors(self->dib, brightness, contrast, gamma, invert)) {
          warn("FreeImage_AdjustColors failed");
        }
        XPUSHs(ST(0)); /* return self */

void
tone_mapping(PDL::IO::Image self, int tmo, double p1=0, double p2=0)
    PPCODE:
        if (tmo == FITMO_DRAGO03 || tmo == FITMO_REINHARD05 || tmo == FITMO_FATTAL02) {
          FIBITMAP *newdib = FreeImage_ToneMapping(self->dib, tmo, p1, p2);
          if (newdib) {
            if (self->dib) FreeImage_Unload(self->dib);
            self->dib = newdib;
          }
          else {
            warn("FreeImage_ToneMapping (tmp=%d) failed", tmo);
          }
        }
        else {
          warn("invalid tone mapping operator");
        }
        XPUSHs(ST(0)); /* return self */

void
rotate(PDL::IO::Image self, double angle, ...)
    PPCODE:
    {
        FIBITMAP *newdib = NULL;
        unsigned bpp = FreeImage_GetBPP(self->dib);
        FREE_IMAGE_TYPE fit = FreeImage_GetImageType(self->dib);

        if (items > 2) {
          switch(fit) {
            case FIT_BITMAP:
              switch(bpp) {
                case 8:
                  {
                    BYTE color = (BYTE)SvUV(ST(2));
                    newdib = FreeImage_Rotate(self->dib, angle, &color);
                  }
                  break;
                case 24:
                case 32:
                  {
                    RGBQUAD color = { 0, 0, 0, 0 };
                    if (items >= 3) color.rgbRed      = (BYTE)SvUV(ST(2));
                    if (items >= 4) color.rgbGreen    = (BYTE)SvUV(ST(3));
                    if (items >= 5) color.rgbBlue     = (BYTE)SvUV(ST(4));
                    if (items >= 6) color.rgbReserved = (BYTE)SvUV(ST(5));
                    newdib = FreeImage_Rotate(self->dib, angle, &color);
                  }
                  break;
                default:
                  /* warn("FAIL: do not know how to handle bpp '%d'", bpp); */
                  break;
              }
              break;
            case FIT_UINT16:
              {
                WORD color = (WORD)SvUV(ST(2));;
                newdib = FreeImage_Rotate(self->dib, angle, &color);
              }
              break;
            case FIT_RGB16:
            case FIT_RGBA16:
              {
                FIRGBA16 color = { 0, 0, 0, 0 };
                if (items >= 3) color.red   = (WORD)SvUV(ST(2));
                if (items >= 4) color.green = (WORD)SvUV(ST(3));
                if (items >= 5) color.blue  = (WORD)SvUV(ST(4));
                if (items >= 6) color.alpha = (WORD)SvUV(ST(5));
                newdib = FreeImage_Rotate(self->dib, angle, &color);
              }
              break;
            case FIT_FLOAT:
              {
                float color = (float)SvNV(ST(2));
                newdib = FreeImage_Rotate(self->dib, angle, &color);
              }
              break;
            case FIT_RGBF:
            case FIT_RGBAF:
              {
                FIRGBAF color = { 0, 0, 0, 0 };
                if (items >= 3) color.red   = (float)SvNV(ST(2));
                if (items >= 4) color.green = (float)SvNV(ST(3));
                if (items >= 5) color.blue  = (float)SvNV(ST(4));
                if (items >= 6) color.alpha = (float)SvNV(ST(5));
                newdib = FreeImage_Rotate(self->dib, angle, &color);
              }
              break;
            default:
              /* warn("FAIL: do not know how to handle image type '%d'", fit); */
              break;
          }
        }

        if (!newdib) {
          newdib = FreeImage_Rotate(self->dib, angle, NULL);
        }

        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_Rotate failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_dither(PDL::IO::Image self, int algorithm=FID_FS)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_Dither(self->dib, algorithm);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_Dither failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_threshhold(PDL::IO::Image self, unsigned threshold=127)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_Threshold(self->dib, (BYTE)threshold);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_Threshold failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_quantize(PDL::IO::Image self, int quantize=FIQ_WUQUANT)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ColorQuantize(self->dib, quantize);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ColorQuantize failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_4bpp(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo4Bits(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo4Bits failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_8bpp(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo8Bits(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo8Bits failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_8bpp_grey(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertToGreyscale(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertToGreyscale failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_16bpp_555(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo16Bits555(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo16Bits555 failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_16bpp_565(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo16Bits565(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo16Bits565 failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_24bpp(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo24Bits(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo24Bits failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
color_to_32bpp(PDL::IO::Image self)
    PPCODE:
    {
        FIBITMAP *newdib = FreeImage_ConvertTo32Bits(self->dib);
        if (newdib) {
          if (self->dib) FreeImage_Unload(self->dib);
          self->dib = newdib;
        }
        else {
          warn("FreeImage_ConvertTo32Bits failed");
        }
        XPUSHs(ST(0)); /* return self */
    }

void
rescale(PDL::IO::Image self, int dst_width=0, int dst_height=0, int filter=FILTER_CATMULLROM)
    PPCODE:
    {
        if (dst_height<=0 && dst_width>0) {
          double ratio = (double)dst_width / (double)FreeImage_GetWidth(self->dib);
          dst_height   = (int)floor(0.5 + ratio * (double)FreeImage_GetHeight(self->dib));
        }
        else if (dst_width<=0 && dst_height>0) {
          double ratio = (double)dst_height / (double)FreeImage_GetHeight(self->dib);
          dst_width    = (int)floor(0.5 + ratio * (double)FreeImage_GetWidth(self->dib));
        }
        if (dst_height>0 && dst_width>0) {
          FIBITMAP *newdib = FreeImage_Rescale(self->dib, dst_width, dst_height, filter);
          if (newdib) {
            if (self->dib) FreeImage_Unload(self->dib);
            self->dib = newdib;
          }
          else {
            warn("FreeImage_Rescale failed");
          }
        }
        XPUSHs(ST(0)); /* return self */
    }

void
rescale_pct(PDL::IO::Image self, double dst_width_pct=0, double dst_height_pct=0, int filter=FILTER_CATMULLROM)
    PPCODE:
    {
        int dst_height = (int)floor(0.5 + (double)FreeImage_GetHeight(self->dib) * dst_height_pct / 100.0);
        int dst_width  = (int)floor(0.5 + (double)FreeImage_GetWidth(self->dib)  * dst_width_pct  / 100.0);

        if (dst_height<=0 && dst_width>0) {
          double ratio = (double)dst_width / (double)FreeImage_GetWidth(self->dib);
          dst_height   = (int)floor(0.5 + ratio * (double)FreeImage_GetHeight(self->dib));
        }
        else if (dst_width<=0 && dst_height>0) {
          double ratio = (double)dst_height / (double)FreeImage_GetHeight(self->dib);
          dst_width    = (int)floor(0.5 + ratio * (double)FreeImage_GetWidth(self->dib));
        }
        if (dst_height>0 && dst_width>0) {
          FIBITMAP *newdib = FreeImage_Rescale(self->dib, dst_width, dst_height, filter);
          if (newdib) {
            if (self->dib) FreeImage_Unload(self->dib);
            self->dib = newdib;
          }
          else {
            warn("FreeImage_Rescale failed");
          }
        }
        XPUSHs(ST(0)); /* return self */
    }

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++) {



( run in 1.841 second using v1.01-cache-2.11-cpan-5511b514fd6 )