File indexing completed on 2025-01-05 03:57:05

0001 /* -*- C++ -*-
0002  * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
0003  *
0004  LibRaw is free software; you can redistribute it and/or modify
0005  it under the terms of the one of two licenses as you choose:
0006 
0007 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0008    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0009 
0010 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0011    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0012 
0013  */
0014 
0015 #include "../../internal/libraw_cxx_defs.h"
0016 
0017 libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *errcode)
0018 {
0019   if (!T.thumb)
0020   {
0021     if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
0022                          load_raw == &LibRaw::broadcom_load_raw) // RPi
0023     )
0024     {
0025       if (errcode)
0026         *errcode = LIBRAW_NO_THUMBNAIL;
0027     }
0028     else
0029     {
0030       if (errcode)
0031         *errcode = LIBRAW_OUT_OF_ORDER_CALL;
0032     }
0033     return NULL;
0034   }
0035 
0036   if (T.tlength < 64u)
0037   {
0038       if (errcode)
0039           *errcode = EINVAL;
0040       return NULL;
0041   }
0042 
0043   if (INT64(T.tlength) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB)
0044   {
0045       if (errcode)
0046           *errcode = LIBRAW_TOO_BIG;
0047       return NULL;
0048   }
0049 
0050   if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
0051   {
0052     libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
0053         sizeof(libraw_processed_image_t) + T.tlength);
0054 
0055     if (!ret)
0056     {
0057       if (errcode)
0058         *errcode = ENOMEM;
0059       return NULL;
0060     }
0061 
0062     memset(ret, 0, sizeof(libraw_processed_image_t));
0063     ret->type = LIBRAW_IMAGE_BITMAP;
0064     ret->height = T.theight;
0065     ret->width = T.twidth;
0066     if (T.tcolors > 0 && T.tcolors < 4)
0067         ret->colors = T.tcolors;
0068     else
0069         ret->colors = 3; // defaults
0070     ret->bits = 8;
0071     ret->data_size = T.tlength;
0072     memmove(ret->data, T.thumb, T.tlength);
0073     if (errcode)
0074       *errcode = 0;
0075     return ret;
0076   }
0077   else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
0078   {
0079     ushort exif[5];
0080     int mk_exif = 0;
0081     if (strcmp(T.thumb + 6, "Exif"))
0082       mk_exif = 1;
0083 
0084     int dsize = T.tlength + mk_exif * (sizeof(exif) + sizeof(tiff_hdr));
0085 
0086     libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
0087         sizeof(libraw_processed_image_t) + dsize);
0088 
0089     if (!ret)
0090     {
0091       if (errcode)
0092         *errcode = ENOMEM;
0093       return NULL;
0094     }
0095 
0096     memset(ret, 0, sizeof(libraw_processed_image_t));
0097 
0098     ret->type = LIBRAW_IMAGE_JPEG;
0099     ret->data_size = dsize;
0100 
0101     ret->data[0] = 0xff;
0102     ret->data[1] = 0xd8;
0103     if (mk_exif)
0104     {
0105       struct tiff_hdr th;
0106       memcpy(exif, "\xff\xe1  Exif\0\0", 10);
0107       exif[1] = htons(8 + sizeof th);
0108       memmove(ret->data + 2, exif, sizeof(exif));
0109       tiff_head(&th, 0);
0110       memmove(ret->data + (2 + sizeof(exif)), &th, sizeof(th));
0111       memmove(ret->data + (2 + sizeof(exif) + sizeof(th)), T.thumb + 2,
0112               T.tlength - 2);
0113     }
0114     else
0115     {
0116       memmove(ret->data + 2, T.thumb + 2, T.tlength - 2);
0117     }
0118     if (errcode)
0119       *errcode = 0;
0120     return ret;
0121   }
0122   else
0123   {
0124     if (errcode)
0125       *errcode = LIBRAW_UNSUPPORTED_THUMBNAIL;
0126     return NULL;
0127   }
0128 }
0129 
0130 // jlb
0131 // macros for copying pixels to either BGR or RGB formats
0132 #define FORBGR for (c = P1.colors - 1; c >= 0; c--)
0133 #define FORRGB for (c = 0; c < P1.colors; c++)
0134 
0135 void LibRaw::get_mem_image_format(int *width, int *height, int *colors,
0136                                   int *bps) const
0137 
0138 {
0139   *width = S.width;
0140   *height = S.height;
0141   if (imgdata.progress_flags < LIBRAW_PROGRESS_FUJI_ROTATE)
0142   {
0143     if (O.use_fuji_rotate)
0144     {
0145       if (IO.fuji_width)
0146       {
0147         int fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
0148         *width = (ushort)(fuji_width / sqrt(0.5));
0149         *height = (ushort)((*height - fuji_width) / sqrt(0.5));
0150       }
0151       else
0152       {
0153         if (S.pixel_aspect < 0.995)
0154           *height = (ushort)(*height / S.pixel_aspect + 0.5);
0155         if (S.pixel_aspect > 1.005)
0156           *width = (ushort)(*width * S.pixel_aspect + 0.5);
0157       }
0158     }
0159   }
0160   if (S.flip & 4)
0161   {
0162     std::swap(*width, *height);
0163   }
0164   *colors = P1.colors;
0165   *bps = O.output_bps;
0166 }
0167 
0168 int LibRaw::copy_mem_image(void *scan0, int stride, int bgr)
0169 
0170 {
0171   // the image memory pointed to by scan0 is assumed to be in the format
0172   // returned by get_mem_image_format
0173   if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) <
0174       LIBRAW_PROGRESS_PRE_INTERPOLATE)
0175     return LIBRAW_OUT_OF_ORDER_CALL;
0176 
0177   if (libraw_internal_data.output_data.histogram)
0178   {
0179     int perc, val, total, t_white = 0x2000, c;
0180     perc = S.width * S.height * O.auto_bright_thr;
0181     if (IO.fuji_width)
0182       perc /= 2;
0183     if (!((O.highlight & ~2) || O.no_auto_bright))
0184       for (t_white = c = 0; c < P1.colors; c++)
0185       {
0186         for (val = 0x2000, total = 0; --val > 32;)
0187           if ((total += libraw_internal_data.output_data.histogram[c][val]) >
0188               perc)
0189             break;
0190         if (t_white < val)
0191           t_white = val;
0192       }
0193     gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright);
0194   }
0195 
0196   int s_iheight = S.iheight;
0197   int s_iwidth = S.iwidth;
0198   int s_width = S.width;
0199   int s_hwight = S.height;
0200 
0201   S.iheight = S.height;
0202   S.iwidth = S.width;
0203 
0204   if (S.flip & 4)
0205     SWAP(S.height, S.width);
0206   uchar *ppm;
0207   ushort *ppm2;
0208   int c, row, col, soff, rstep, cstep;
0209 
0210   soff = flip_index(0, 0);
0211   cstep = flip_index(0, 1) - soff;
0212   rstep = flip_index(1, 0) - flip_index(0, S.width);
0213 
0214   for (row = 0; row < S.height; row++, soff += rstep)
0215   {
0216     uchar *bufp = ((uchar *)scan0) + row * stride;
0217     ppm2 = (ushort *)(ppm = bufp);
0218     // keep trivial decisions in the outer loop for speed
0219     if (bgr)
0220     {
0221       if (O.output_bps == 8)
0222       {
0223         for (col = 0; col < S.width; col++, soff += cstep)
0224           FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
0225       }
0226       else
0227       {
0228         for (col = 0; col < S.width; col++, soff += cstep)
0229           FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
0230       }
0231     }
0232     else
0233     {
0234       if (O.output_bps == 8)
0235       {
0236         for (col = 0; col < S.width; col++, soff += cstep)
0237           FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
0238       }
0239       else
0240       {
0241         for (col = 0; col < S.width; col++, soff += cstep)
0242           FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
0243       }
0244     }
0245 
0246     //            bufp += stride;           // go to the next line
0247   }
0248 
0249   S.iheight = s_iheight;
0250   S.iwidth = s_iwidth;
0251   S.width = s_width;
0252   S.height = s_hwight;
0253 
0254   return 0;
0255 }
0256 #undef FORBGR
0257 #undef FORRGB
0258 
0259 libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
0260 
0261 {
0262   int width, height, colors, bps;
0263   get_mem_image_format(&width, &height, &colors, &bps);
0264   int stride = width * (bps / 8) * colors;
0265   unsigned ds = height * stride;
0266   libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
0267       sizeof(libraw_processed_image_t) + ds);
0268   if (!ret)
0269   {
0270     if (errcode)
0271       *errcode = ENOMEM;
0272     return NULL;
0273   }
0274   memset(ret, 0, sizeof(libraw_processed_image_t));
0275 
0276   // metadata init
0277   ret->type = LIBRAW_IMAGE_BITMAP;
0278   ret->height = height;
0279   ret->width = width;
0280   ret->colors = colors;
0281   ret->bits = bps;
0282   ret->data_size = ds;
0283   copy_mem_image(ret->data, stride, 0);
0284 
0285   return ret;
0286 }
0287 
0288 void LibRaw::dcraw_clear_mem(libraw_processed_image_t *p)
0289 {
0290   if (p)
0291     ::free(p);
0292 }