int TransformerRelease(Transformer *transformer) { TransformerSetBitmap(transformer, NULL, 0, 0); if (yobject_release((yobject*) transformer) != YOSAL_OK) { return YMAGINE_ERROR; } return YMAGINE_OK; }
Transformer* TransformerCreate() { Transformer* transformer; transformer = (Transformer*) yobject_create(sizeof(Transformer), TransformerReleaseCallback); if (transformer == NULL) { return NULL; } transformer->srcw = 0; transformer->srch = 0; transformer->destw = 0; transformer->desth = 0; transformer->nexty = 0; transformer->nextyf = YFIXED_ZERO; transformer->cury = transformer->nexty; transformer->curyf = transformer->nextyf; transformer->desty = -1; transformer->stashedweight = YFIXED_ZERO; transformer->srcrect.x = 0; transformer->srcrect.y = 0; transformer->srcrect.width = 0; transformer->srcrect.height = 0; transformer->destrect.x = 0; transformer->destrect.y = 0; transformer->destrect.width = 0; transformer->destrect.height = 0; /* 3x3 convolution */ transformer->convmode = TRANSFORMER_CONVOLUTION_NONE; transformer->convlinecount = 0; transformer->convcprev = NULL; transformer->convcur = NULL; transformer->convnext = NULL; /* transformer state */ transformer->srcline = -1; transformer->srcmode = VBITMAP_COLOR_RGBA; transformer->srcbpp = colorBpp(transformer->srcmode); transformer->destmode = VBITMAP_COLOR_RGBA; transformer->destbpp = colorBpp(transformer->destmode); transformer->destpitch = 0; transformer->destbuf = NULL; transformer->destaligned = NULL; transformer->statsmode = 0; transformer->statscount = 0; transformer->statsbuf = NULL; transformer->histr = NULL; transformer->histg = NULL; transformer->histb = NULL; transformer->histlum = NULL; transformer->scaledbuf = NULL; transformer->curbuf = NULL; transformer->tmpbuf = NULL; transformer->bltmap = NULL; transformer->obitmap = NULL; TransformerSetBitmap(transformer, NULL, 0, 0); transformer->shader = NULL; transformer->sharpen = 0.0f; /* Transformer writer callback */ transformer->writer = NULL; transformer->writerdata = NULL; return transformer; }
static YOPTIMIZE_SPEED int decompress_jpeg(struct jpeg_decompress_struct *cinfo, struct jpeg_compress_struct *cinfoout, JCOPY_OPTION copyoption, Vbitmap *vbitmap, YmagineFormatOptions *options) { int scanlines; int nlines; int totallines; int j; int scalenum = -1; JSAMPARRAY buffer; Vrect srcrect; Vrect destrect; size_t row_stride; Transformer *transformer; PixelShader *shader = NULL; int iwidth, iheight; float sharpen = 0.0f; if (vbitmap == NULL && cinfoout == NULL) { /* No output specified */ return 0; } if (options == NULL) { /* Options argument is mandatory */ return 0; } iwidth = cinfo->image_width; iheight = cinfo->image_height; if (YmaginePrepareTransform(vbitmap, options, iwidth, iheight, &srcrect, &destrect) != YMAGINE_OK) { return 0; } shader = options->pixelshader; sharpen = options->sharpen; /* Define if image can be pre-subsampled by a ratio n/8 (n=1..7) */ scalenum = GetScaleNum(destrect.width, destrect.height, srcrect.width, srcrect.height, options->scalemode); if (scalenum > 0 && scalenum < 8) { cinfo->scale_num = scalenum; cinfo->scale_denom = 8; } /* Compute actual output dimension for image returned by decoder */ jpeg_calc_output_dimensions(cinfo); #if YMAGINE_DEBUG_JPEG ALOGD("src=%dx%d@%d,%d dst=%dx%d@%d,%d", srcrect.width, srcrect.height, srcrect.x, srcrect.y, destrect.width, destrect.height, destrect.x, destrect.y); ALOGD("size: %dx%d req: %dx%d %s -> scale: %d/%d output: %dx%d components: %d", iwidth, iheight, destrect.width, destrect.height, Ymagine_scaleModeStr(options->scalemode), cinfo->scale_num, cinfo->scale_denom, cinfo->output_width, cinfo->output_height, cinfo->output_components); #endif /* Scale the crop region to reflect scaling ratio applied by JPEG decoder */ if (cinfo->image_width != cinfo->output_width) { srcrect.x = (srcrect.x * cinfo->output_width) / cinfo->image_width; srcrect.width = (srcrect.width * cinfo->output_width) / cinfo->image_width; } if (cinfo->image_height != cinfo->output_height) { srcrect.y = (srcrect.y * cinfo->output_height) / cinfo->image_height; srcrect.height = (srcrect.height * cinfo->output_height) / cinfo->image_height; } /* Number of scan lines to handle per pass. Making it larger actually doesn't help much */ row_stride = cinfo->output_width * cinfo->output_components; scanlines = (32 * 1024) / row_stride; if (scanlines < 1) { scanlines = 1; } if (scanlines > cinfo->output_height) { scanlines = cinfo->output_height; } #if YMAGINE_DEBUG_JPEG ALOGD("BITMAP @(%d,%d) %dx%d bpp=%d -> @(%dx%d) %dx%d (%d lines)", srcrect.x, srcrect.y, srcrect.width, srcrect.height, JpegPixelSize(cinfo->out_color_space), destrect.x, destrect.y, destrect.width, destrect.height, scanlines); #endif /* Resize encoder */ if (cinfoout != NULL) { cinfoout->image_width = destrect.width; cinfoout->image_height = destrect.height; jpeg_start_compress(cinfoout, TRUE); if (copyoption != JCOPYOPT_NONE) { /* Copy to the output file any extra markers that we want to preserve */ jcopy_markers_execute(cinfo, cinfoout, copyoption); } } /* Resize target bitmap */ if (vbitmap != NULL) { if (options->resizable) { destrect.x = 0; destrect.y = 0; if (VbitmapResize(vbitmap, destrect.width, destrect.height) != YMAGINE_OK) { return 0; } } if (VbitmapType(vbitmap) == VBITMAP_NONE) { /* Decode bounds only, return positive number (number of lines) on success */ return VbitmapHeight(vbitmap); } } if (!jpeg_start_decompress(cinfo)) { if (cinfoout != NULL) { jpeg_abort_compress(cinfoout); } return 0; } buffer = (JSAMPARRAY) (*cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, scanlines); if (buffer == NULL) { if (cinfoout != NULL) { jpeg_abort_compress(cinfoout); } jpeg_abort_decompress(cinfo); return 0; } totallines = 0; transformer = TransformerCreate(); if (transformer != NULL) { TransformerSetScale(transformer, cinfo->output_width, cinfo->output_height, destrect.width, destrect.height); TransformerSetRegion(transformer, srcrect.x, srcrect.y, srcrect.width, srcrect.height); if (vbitmap != NULL) { TransformerSetMode(transformer, JpegPixelMode(cinfo->out_color_space), VbitmapColormode(vbitmap)); TransformerSetBitmap(transformer, vbitmap, destrect.x, destrect.y); } else { TransformerSetMode(transformer, JpegPixelMode(cinfo->out_color_space), JpegPixelMode(cinfoout->in_color_space)); TransformerSetWriter(transformer, JpegWriter, cinfoout); } TransformerSetShader(transformer, shader); TransformerSetSharpen(transformer, sharpen); } while (transformer != NULL && cinfo->output_scanline < cinfo->output_height) { nlines = jpeg_read_scanlines(cinfo, buffer, scanlines); if (nlines <= 0) { /* Decoding error */ ALOGD("decoding error (nlines=%d)", nlines); break; } for (j = 0; j < nlines; j++) { if (TransformerPush(transformer, (const char*) buffer[j]) != YMAGINE_OK) { TransformerRelease(transformer); transformer = NULL; break; } totallines++; } } /* Clean up */ if (transformer != NULL) { TransformerRelease(transformer); } if (cinfo->output_scanline > 0 && cinfo->output_scanline == cinfo->output_height) { /* Do normal cleanup if whole image has been read and decoded */ jpeg_finish_decompress(cinfo); if (cinfoout != NULL) { jpeg_finish_compress(cinfoout); } } else { /* else early abort */ jpeg_abort_decompress(cinfo); if (cinfoout != NULL) { jpeg_abort_compress(cinfoout); } totallines = 0; } return totallines; }