author Tony Cook Fri, 24 Aug 2007 07:27:18 +0000 (07:27 +0000) committer Tony Cook Fri, 24 Aug 2007 07:27:18 +0000 (07:27 +0000)
This needs some cleanup:

- integrate the extra tests supplied
- test the method she didn't
- foolproofing
- documentation

https://rt.cpan.org/Ticket/Display.html?id=28142

 Imager.pm patch | blob | blame | history Imager.xs patch | blob | blame | history datatypes.c patch | blob | blame | history image.c patch | blob | blame | history

index 28a72bf..065b29b 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -3269,6 +3269,33 @@ sub getcolorcount {
return (\$rc==-1? undef : \$rc);
}

return (\$rc==-1? undef : \$rc);
}

+# Returns a reference to a hash. The keys are colour named (packed) and the
+# values are the number of pixels in this colour.
+sub getcolorusagehash {
+    my \$self = shift;
+    my \$channels= \$self->getchannels;
+    # We don't want to look at the alpha channel, because some gifs using it
+    # doesn't define it for every colour (but only for some)
+    \$channels -= 1 if \$channels == 2 or \$channels == 4;
+    my %colour_use;
+    my \$height = \$self->getheight;
+    for my \$y (0 .. \$height - 1) {
+        my \$colours = \$self->getsamples(y => \$y, channels => [ 0 .. \$channels - 1 ]);
+        while (length \$colours) {
+            \$colour_use{ substr(\$colours, 0, \$channels, '') }++;
+        }
+    }
+    return \%colour_use;
+}
+
+# This will return a ordered array of the colour usage. Kind of the sorted
+# version of the values of the hash returned by getcolorusagehash.
+# You might want to add safety checks and change the names, etc...
+sub getcolorusage {
+  my \$self=shift;
+  return get_anonymous_colour_usage (\$self);
+}
+
# draw string to an image

sub string {
# draw string to an image

sub string {
index c44841c..0ccba04 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -2972,6 +2972,22 @@ i_count_colors(im,maxc)
Imager::ImgRaw     im
int     maxc

Imager::ImgRaw     im
int     maxc

+void
+get_anonymous_colour_usage(Imager::ImgRaw im)
+    PPCODE:
+        int i;
+        unsigned int ** col_usage = (unsigned int **) mymalloc(sizeof(unsigned int *));
+        unsigned int * p;
+        int col_cnt = get_anonymous_color_histo(im, col_usage);
+        EXTEND(SP, col_cnt);
+        p = *col_usage;
+        for (i = 0; i < col_cnt; )  {
+            PUSHs(sv_2mortal(newSViv( p[i++])));
+        }
+        myfree(p);
+        myfree(col_usage);
+        XSRETURN(col_cnt);
+

Imager::ImgRaw
i_transform(im,opx,opy,parm)

Imager::ImgRaw
i_transform(im,opx,opy,parm)
index 9c04b18..dfbf6a6 100644 (file)
@@ -216,21 +216,22 @@ int
octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b) {
struct octt *c;
int i,cm;
octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b) {
struct octt *c;
int i,cm;
-  int ci,idx;
+  int ci;
int rc;
rc=0;
c=ct;
/*  printf("[r,g,b]=[%d,%d,%d]\n",r,g,b); */
int rc;
rc=0;
c=ct;
/*  printf("[r,g,b]=[%d,%d,%d]\n",r,g,b); */
-  ct->cnt++;
for(i=7;i>-1;i--) {
cm=1<<i;
ci=((!!(r&cm))<<2)+((!!(g&cm))<<1)+!!(b&cm);
/* printf("idx[%d]=%d\n",i,ci); */
for(i=7;i>-1;i--) {
cm=1<<i;
ci=((!!(r&cm))<<2)+((!!(g&cm))<<1)+!!(b&cm);
/* printf("idx[%d]=%d\n",i,ci); */
-    if (c->t[ci] == NULL) { c->t[ci]=octt_new(); rc=1; }
+    if (c->t[ci] == NULL) {
+      c->t[ci]=octt_new();
+      rc=1;
+    }
c=c->t[ci];
c=c->t[ci];
-    c->cnt++;
-    idx[i]=ci;
}
}
+  c->cnt++;  /* New. The only thing really needed (I think) */
return rc;
}

return rc;
}

@@ -267,3 +268,22 @@ octt_count(struct octt *ct,int *tot,int max,int *overflow) {
if (!c) (*tot)++;
if ( (*tot) > (*overflow) ) *overflow=0;
}
if (!c) (*tot)++;
if ( (*tot) > (*overflow) ) *overflow=0;
}
+
+/* This whole function is new */
+/* walk through the tree and for each colour, store its seen count in the
+   space pointed by *col_usage_it_adr */
+void
+octt_histo(struct octt *ct, unsigned int **col_usage_it_adr) {
+    int i,c;
+    c = 0;
+    for(i = 0; i < 8; i++)
+        if (ct->t[i] != NULL) {
+            c++;
+        }
+    if (!c) {
+    }
+}
+
+
diff --git a/image.c b/image.c
index 4f21c16..dfef965 100644 (file)
--- a/image.c
+++ b/image.c
to indicate that it was more than max colors

=cut
*/

=cut
*/
+/* This function has been changed and is now faster. It's using
+ * i_gsamp instead of i_gpix */
int
i_count_colors(i_img *im,int maxc) {
struct octt *ct;
int x,y;
int
i_count_colors(i_img *im,int maxc) {
struct octt *ct;
int x,y;
-  int xsize,ysize;
-  i_color val;
int colorcnt;
int colorcnt;
-
-  mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
-
-  xsize=im->xsize;
-  ysize=im->ysize;
-  ct=octt_new();
-  colorcnt=0;
-  for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
-    i_gpix(im,x,y,&val);
-    if (colorcnt > maxc) { octt_delete(ct); return -1; }
+  int channels;
+  int *samp_chans;
+  i_sample_t * samp;
+
+  int xsize = im->xsize;
+  int ysize = im->ysize;
+  if (im->channels >= 3) {
+    samp_chans = NULL;
+  }
+  else {
+    channels = channels = channels = 0;
+    samp_chans = channels;
}
}
+  int samp_cnt = 3 * xsize;
+  ct = octt_new();
+
+  samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
+
+  colorcnt = 0;
+  for(y = 0; y < ysize; ) {
+      i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
+      for(x = 0; x < samp_cnt; ) {
+          colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
+          x += 3;
+          if (colorcnt > maxc) {
+              octt_delete(ct);
+              return -1;
+          }
+      }
+  }
+  myfree(samp);
octt_delete(ct);
return colorcnt;
}

octt_delete(ct);
return colorcnt;
}

+/* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
+ * (adapted from the Numerical Recipes)
+ */
+/* Needed by get_anonymous_color_histo */
+void hpsort(unsigned int n, int *ra) {
+    unsigned int i,
+                 ir,
+                 j,
+                 l,
+                 rra;
+
+    if (n < 2) return;
+    l = n >> 1;
+    ir = n - 1;
+    for(;;) {
+        if (l > 0) {
+            rra = ra[--l];
+        }
+        else {
+            rra = ra[ir];
+            ra[ir] = ra;
+            if (--ir == 0) {
+                ra = rra;
+                break;
+            }
+        }
+        i = l;
+        j = 2 * l + 1;
+        while (j <= ir) {
+            if (j < ir && ra[j] < ra[j+1]) j++;
+            if (rra < ra[j]) {
+                ra[i] = ra[j];
+                i = j;
+                j++; j <<= 1; j--;
+            }
+            else break;
+        }
+        ra[i] = rra;
+    }
+}
+
+/* This function constructs an ordered list which represents how much the
+ * different colors are used. So for instance (100, 100, 500) means that one
+ * color is used for 500 pixels, another for 100 pixels and another for 100
+ * pixels. It's tuned for performance. You might not like the way I've hardcoded
+ * the maxc ;-) and you might want to change the name... */
+/* Uses octt_histo */
+int
+get_anonymous_color_histo(i_img *im, unsigned int **col_usage) {
+    struct octt *ct;
+    int x,y,i;
+    int colorcnt;
+    int maxc = 10000000;
+    unsigned int *col_usage_it;
+    i_sample_t * samp;
+
+    int xsize = im->xsize;
+    int ysize = im->ysize;
+    int samp_cnt = 3 * xsize;
+    ct = octt_new();
+
+    samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
+
+    colorcnt = 0;
+    for(y = 0; y < ysize; ) {
+        i_gsamp(im, 0, xsize, y++, samp, NULL, 3);
+        for(x = 0; x < samp_cnt; ) {
+            colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
+            x += 3;
+            if (colorcnt > maxc) {
+                octt_delete(ct);
+                return -1;
+            }
+        }
+    }
+    myfree(samp);
+    /* Now that we know the number of colours... */
+    col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * 2 * sizeof(unsigned int));
+    octt_histo(ct, &col_usage_it);
+    hpsort(colorcnt, *col_usage);
+    octt_delete(ct);
+    return colorcnt;
+}
+
+
+
/*
=back

/*
=back
{"ft_lang_label":"__label__en","ft_lang_prob":0.659779,"math_prob":0.98586935,"size":1927,"snap":"2021-43-2021-49","text_gpt3_token_len":694,"char_repetition_ratio":0.13416536,"word_repetition_ratio":0.0074074073,"special_character_ratio":0.45718732,"punctuation_ratio":0.22527473,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.994955,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-10-21T09:41:06Z\",\"WARC-Record-ID\":\"<urn:uuid:7fcee529-d130-4ce5-b25a-5ad68e73fed6>\",\"Content-Length\":\"42079\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:d4fb8e5e-a404-46cb-af4d-b0ad788f38c8>\",\"WARC-Concurrent-To\":\"<urn:uuid:51c70ada-157e-44d7-a8fd-39f7b7332274>\",\"WARC-IP-Address\":\"172.105.169.56\",\"WARC-Target-URI\":\"http://git.imager.perl.org/imager.git/commitdiff/fe622da1a9411858f65f665bb33f4d065f01da97?ds=sidebyside\",\"WARC-Payload-Digest\":\"sha1:WTQUFIK3QBVAZ4NHTSJ3735LYLUU7WUF\",\"WARC-Block-Digest\":\"sha1:FGRTH3PXPO7ERO67GLRE4PHQMFEEQEVI\",\"WARC-Identified-Payload-Type\":\"application/xhtml+xml\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-43/CC-MAIN-2021-43_segments_1634323585382.32_warc_CC-MAIN-20211021071407-20211021101407-00324.warc.gz\"}"}