Schaal factoren vraag

Status
Niet open voor verdere reacties.

tim687

Terugkerende gebruiker
Lid geworden
25 apr 2010
Berichten
1.774
Beste leden,

Ik heb een probleem met betrekking tot het schalen van een afbeelding.

De afbeelding heeft een resolutie van 4096 x 2160. Omdat de afbeelding in een ImageView wordt geladen (waarbij een Bitmap texture wordt gebruikt) heeft deze texture een maximale grootte. Dit weet mijn app (hij haalt dit op). Omdat de max. grootte niet mag worden overschreden, wordt de afbeelding verkleint als dit nodig is.
De HTC One X heeft een max. texture size van 2048 x 2048, de afbeelding wordt dus 2 keer verkleint (de breedte en de hoogte om de aspect ratio te behouden). De originele bitmap van 4096 x 2160 wordt wel bewaard, omdat er vanuit deze bitmap "gecropped" moet worden (zo blijft de kwaliteit behouden).

Dus even ter samenvatting. De bitmap die in de ImageView wordt geladen heeft een resolutie van 2048 bij 1080, en de originele afbeelding heeft een resolutie van 4096 x 2160.
Omdat de afbeelding niet in zijn volledige resolutie in de imageView past, wordt deze (!dit is dus de afbeelding met een resolutie van 2048 x 1080!) nog een keer verkleint (dit gebeurd allemaal automatisch, door de library die ik gebruik)

De crop aspect ratio (per as, op een schaal van 10) wordt berekend met de formule


Code:
public double calculateAspectRatio(int desiredPixelCount, int originalPixelCount) {
        return (double) (((double) desiredPixelCount / (double) originalPixelCount) * 10);
    }


De juiste aspectratio voor de uiteindelijke afbeelding moet dus 1440/4096 x 10 = 3,515625 zijn. (de max texture size is tijdens deze berekening nog niet bekend)


Om de gecroppte afbeelding te berekenen doet de library dit:



Code:
/**
     * Gets the cropped image based on the current crop window.
     * 
     * @return a new Bitmap representing the cropped image
     */
    public Bitmap getCroppedImage() {

        final Rect displayedImageRect = ImageViewUtil.getBitmapRectCenterInside(mBitmap, mImageView);

        System.out.println("Times smaller = " + timesSmaller); // timesSmaller is de verhouding tussen de maximale grootte afbeelding en de originele afbeelding

        // Get the scale factor between the actual Bitmap dimensions and the
        // displayed dimensions for width.
        final float actualImageWidth = mBitmap.getWidth();
        final float displayedImageWidth = displayedImageRect.width();
        final float scaleFactorWidth = (actualImageWidth / displayedImageWidth);

        // Get the scale factor between the actual Bitmap dimensions and the
        // displayed dimensions for height.
        final float actualImageHeight = mBitmap.getHeight();
        final float displayedImageHeight = displayedImageRect.height();
        final float scaleFactorHeight = (actualImageHeight / displayedImageHeight);

        // Get crop window position relative to the displayed image.
        final float cropWindowX = Edge.LEFT.getCoordinate() - displayedImageRect.left;
        final float cropWindowY = Edge.TOP.getCoordinate() - displayedImageRect.top;
        final float cropWindowWidth = Edge.getWidth();
        final float cropWindowHeight = Edge.getHeight();

        // Scale the crop window position to the actual size of the Bitmap.
        final float actualCropX = cropWindowX * scaleFactorWidth;
        final float actualCropY = cropWindowY * scaleFactorHeight;
        final float actualCropWidth = cropWindowWidth * scaleFactorWidth;
        final float actualCropHeight = cropWindowHeight * scaleFactorHeight;

        // Crop the subset from the original Bitmap.
        final Bitmap croppedBitmap = Bitmap.createBitmap(mBitmap,
                                                         (int) actualCropX,
                                                         (int) actualCropY,
                                                         (int) actualCropWidth,
                                                         (int) actualCropHeight);

        return croppedBitmap;
    }

Hier is een lijst met alle waardes tijdens runtime:

Code:
timesSmaller = 2
actualImageWidth = 4096.0
displayedImageWidth = 720.0
scaleFactorWidth = 5.688889
actualImageHeight = 2160.0
displayedImageHeight = 380.0
scaleFactorHeight = 5.6842103
cropWindowX = 72.0
cropWindowY = 70.0
cropWindowWidth = 576.0
cropWindowHeight = 304.0
actualCropX = 409.6
actualCropY = 397.8947
actualCropWidth = 3276.8
actualCropHeight = 1727.9999


De afbeelding wordt dus gecropped naar een resolutie van 3276.8 x 1727.9999. Dit moet 1440x720 zijn (we zitten er ietsje vanaf :p)

Hoe kom ik op deze resolutie??
Moet ik de aspect ratio van de crop size berekenen met de max texture size? Of hoef ik daar geen rekening mee de houden?


Het zou top zijn als iemand me hierbij kon helpen!

Bedankt,

Tim
 
Laatst bewerkt:
In theorie is gemakkelijk 1/2 1/4 1/8
1/2 wil zeggen dat er één pixelrij blijft de ander verdwijnt
vervolgens maak je een object die diferentie doet met een berekening (met interface)

dus je kan je pixel gaan berekenen met de verhouding van rgb nu krijg je een verhouding rgbx en rgby
de verhouding is de pixel en verhouding met de volgende verdwijnende pixel en de volgende
zo zijn er programmas die dus 1/2 eerste verhouding en correctie tweede verhouding 1/4 dit bij verkleinen

nu vergroten wil zeggen dat 1 pixel 4 pixels wordt nu iets moeilijker om beeld juist te houden krijg je verhoudingen

stel donker licht zal afwijkingen van meer 50% genegeert worden en geen diferentie ondergaan behoud van contrast nu vervolgens ga je dus voor light up or dark up en hierdoor word dus de bijkomende pixel dark of light nu gebeurt dat ook meestal met 1/2+1/4+1/8
 
Hmm,

Bedankt voor de berekening, ik heb het alleen anders opgelost. Ik heb eerst de bitmap toegevoegd, en daarna op de gehele canvas de matrix toegepast.

Toch nog bedankt!

Tim
 
In theorie is gemakkelijk 1/2 1/4 1/8
1/2 wil zeggen dat er één pixelrij blijft de ander verdwijnt
vervolgens maak je een object die diferentie doet met een berekening (met interface)

dus je kan je pixel gaan berekenen met de verhouding van rgb nu krijg je een verhouding rgbx en rgby
de verhouding is de pixel en verhouding met de volgende verdwijnende pixel en de volgende
zo zijn er programmas die dus 1/2 eerste verhouding en correctie tweede verhouding 1/4 dit bij verkleinen

nu vergroten wil zeggen dat 1 pixel 4 pixels wordt nu iets moeilijker om beeld juist te houden krijg je verhoudingen

stel donker licht zal afwijkingen van meer 50% genegeert worden en geen diferentie ondergaan behoud van contrast nu vervolgens ga je dus voor light up or dark up en hierdoor word dus de bijkomende pixel dark of light nu gebeurt dat ook meestal met 1/2+1/4+1/8

Ik heb het helemaal anders aangepakt. Ik heb de code omgegooid. Dit is de code nu:

Code:
package com.tim.koers.interfacelift.Utils;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;

import com.google.zxing.client.android.Intents;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import com.tim.koers.interfacelift.Constants.Constants;
import com.tim.koers.interfacelift.Data.Image;
import com.tim.koers.interfacelift.Data.Resolution;
import com.tim.koers.interfacelift.Data.WallpapersResponse;
import com.tim.koers.interfacelift.HTTP.Fetcher;
import com.tim.koers.interfacelift.ImageDetails;
import com.tim.koers.interfacelift.MainActivity;
import com.tim.koers.interfacelift.R;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class NotificationService extends Service {

    private PowerManager.WakeLock mWakeLock;

    private SharedPreferences sharedPreferences;

    private static final List<LoadTarget> loadTargetProtectorList = new ArrayList<>();

    private Image image = null;

    public NotificationService() {
    }


    /**
     * This is called on 2.0+ (API level 5 or higher). Returning
     * START_NOT_STICKY tells the system to not restart the service if it is
     * killed because of poor resource (memory/cpu) conditions.
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        handleIntent(intent);

        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        Log.d("Notification Service", "onStartCommand");
        return START_NOT_STICKY;
    }


    /**
     * In onDestroy() we release our wake lock. This ensures that whenever the
     * Service stops (killed for resources, stopSelf() called, etc.), the wake
     * lock will be released.
     */
    public void onDestroy() {
        super.onDestroy();
        mWakeLock.release();
    }

    @Override
    public void onCreate() {
        super.onCreate();

        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        Log.d("Notification Service", "onCreate");

    }


    private void handleIntent(Intent intent) {

        Hardware hardware = new Hardware(this);

        if (sharedPreferences == null) {
            sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        }

        // obtain the wake lock
        PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NotificationService");
        mWakeLock.acquire();

        // check the global background data setting
        ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        if (cm.getActiveNetworkInfo().getType() != ConnectivityManager.TYPE_WIFI) { // This makes sure that the app only syncs when on WiFi
            stopSelf();
            return;
        } else {

            int previousLastId = sharedPreferences.getInt(Constants.Settings.recentImageId, 0);

            Log.d("Notification Service", "last id = " + previousLastId);

            final LinkedHashMap<String, String> methodParams = new LinkedHashMap<>();

            methodParams.put("direction", "older");
            methodParams.put("limit", "1");
            methodParams.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000L));
            try {
                methodParams.put("preview", Resolution.getClosestResolution(hardware.getRealResolution()).toString().replaceAll(" ", ""));
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            Fetcher fetcher = new Fetcher(Constants.HTTP.Methods.wallpapers_by_timestamp, methodParams, WallpapersResponse.class);

            try {
                image = (Image)((List<Object>) fetcher.execute().get()).get(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

            Log.d("Notification Service", "Id of last image from server = " + image.getId());

            if (image.getId() != previousLastId) {
                // New image has been posted!

                LoadTarget loadTarget = new LoadTarget(this);
                loadTargetProtectorList.add(loadTarget);

                Log.d("Notification Service", "Pushing new notification");

                Picasso.with(this).setLoggingEnabled(true);

                Picasso.with(this).load(image.getCustom_preview_url()).into(loadTargetProtectorList.get(0));


            }



        }

        Log.d("Notification Service", "handleIntent(intent) completed");

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.

        handleIntent(intent);
        Log.d("Notification Service", "onBind");

        return null;
    }

    class LoadTarget implements Target{

        private Context context;

        public LoadTarget(Context context) {
            this.context = context;
        }

        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

            NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

            ImageDetails imageDetails = new ImageDetails();

            imageDetails.setImage(image);

            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, imageDetails.getClass()),0);

            int notificationSize = (int)getResources().getDimension(R.dimen.notification_bigIcon_size);

            Bitmap smallerBitmap = Bitmap.createScaledBitmap(bitmap, notificationSize, notificationSize, false);

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
                    .setContentTitle(image.getTitle() + " " + getResources().getString(R.string.has_just_been_uploaded))
                    .setContentText(image.getUser_name())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(smallerBitmap)
                    .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap))
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent);

            notificationManager.notify(1, mBuilder.build());

            Log.d("Notification Service", "Notification pushed!");
        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {

            NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

            ImageDetails imageDetails = new ImageDetails();

            imageDetails.setImage(image);

            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, imageDetails.getClass()),0);

            int notificationSize = (int)getResources().getDimension(R.dimen.notification_bigIcon_size);

            Bitmap smallerBitmap = Bitmap.createScaledBitmap(((BitmapDrawable)ContextCompat.getDrawable(context,R.mipmap.ic_launcher)).getBitmap(), notificationSize, notificationSize, false);

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
                    .setContentTitle(image.getTitle() + " " + getResources().getString(R.string.has_just_been_uploaded))
                    .setContentText(image.getUser_name())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(smallerBitmap)
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent);



            notificationManager.notify(1, mBuilder.build());

            Log.d("Notification Service", "Notification pushed without bigger picture!");

        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }
    }

}

Wat er gebeurd met een afbeelding is dit:

Screenshot_2015-08-23-11-25-39.jpg

Wat gaat hier niet goed?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan